package com.attendance.www.hr.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang3.time.DateUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.attendance.www.hr.beans.ApprovalRecordBean;
import com.attendance.www.hr.beans.AttendanceBean;
import com.attendance.www.hr.beans.EmployeeSpecialBean;
import com.attendance.www.hr.beans.LactationBean;
import com.attendance.www.hr.beans.RequestApprovalBean;
import com.attendance.www.hr.beans.RequestApprovalPageBean;
import com.attendance.www.hr.beans.RequestApprovalParamBean;
import com.attendance.www.hr.beans.RequestApprovalSaveBean;
import com.attendance.www.hr.beans.RequestBean;
import com.attendance.www.hr.beans.RestVacationBean;
import com.attendance.www.hr.beans.RetroactiveApprovalBean;
import com.attendance.www.hr.beans.RetroactiveApprovalPageBean;
import com.attendance.www.hr.beans.RetroactiveApprovalParamBean;
import com.attendance.www.hr.beans.RetroactiveBean;
import com.attendance.www.hr.beans.SchedulWeekBean;
import com.attendance.www.hr.constant.AppConstant;
import com.attendance.www.hr.dao.mapper.ApprovalRecordExtMapper;
import com.attendance.www.hr.dao.mapper.ApprovalRecordMapper;
import com.attendance.www.hr.dao.mapper.ApprovalRuleMapper;
import com.attendance.www.hr.dao.mapper.AttendanceExtMapper;
import com.attendance.www.hr.dao.mapper.AttendanceMapper;
import com.attendance.www.hr.dao.mapper.AttendanceReportExtMapper;
import com.attendance.www.hr.dao.mapper.AttendanceReportMapper;
import com.attendance.www.hr.dao.mapper.DictionaryMapper;
import com.attendance.www.hr.dao.mapper.EmployeeExtMapper;
import com.attendance.www.hr.dao.mapper.EmployeeMapper;
import com.attendance.www.hr.dao.mapper.EmployeeRoleExtMapper;
import com.attendance.www.hr.dao.mapper.EmployeeRoleMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSchedulMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSpecialExtMapper;
import com.attendance.www.hr.dao.mapper.EmployeeSpecialMapper;
import com.attendance.www.hr.dao.mapper.FurloughBalanceMapper;
import com.attendance.www.hr.dao.mapper.HolidayMapper;
import com.attendance.www.hr.dao.mapper.LactationExtMapper;
import com.attendance.www.hr.dao.mapper.LactationMapper;
import com.attendance.www.hr.dao.mapper.LinkAddressMapper;
import com.attendance.www.hr.dao.mapper.PunchTimeMapper;
import com.attendance.www.hr.dao.mapper.RequestApprovalExtMapper;
import com.attendance.www.hr.dao.mapper.RequestExtMapper;
import com.attendance.www.hr.dao.mapper.RequestMapper;
import com.attendance.www.hr.dao.mapper.RequestReportMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveApprovalExtMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveExtMapper;
import com.attendance.www.hr.dao.mapper.RetroactiveMapper;
import com.attendance.www.hr.dao.mapper.RoleMapper;
import com.attendance.www.hr.dao.mapper.SchedulDayMapper;
import com.attendance.www.hr.dao.mapper.SchedulWeekExtMapper;
import com.attendance.www.hr.dao.mapper.SchedulWeekMapper;
import com.attendance.www.hr.dao.mapper.SpecialMapper;
import com.attendance.www.hr.dao.mapper.SystemConfigureMapper;
import com.attendance.www.hr.dao.mapper.TaskMapper;
import com.attendance.www.hr.entitys.ApprovalRecord;
import com.attendance.www.hr.entitys.ApprovalRecordExample;
import com.attendance.www.hr.entitys.ApprovalRule;
import com.attendance.www.hr.entitys.Attendance;
import com.attendance.www.hr.entitys.AttendanceExample;
import com.attendance.www.hr.entitys.Dictionary;
import com.attendance.www.hr.entitys.DictionaryExample;
import com.attendance.www.hr.entitys.Employee;
import com.attendance.www.hr.entitys.EmployeeExample;
import com.attendance.www.hr.entitys.EmployeeRole;
import com.attendance.www.hr.entitys.EmployeeRoleExample;
import com.attendance.www.hr.entitys.EmployeeSchedul;
import com.attendance.www.hr.entitys.EmployeeSchedulExample;
import com.attendance.www.hr.entitys.EmployeeSpecialExample;
import com.attendance.www.hr.entitys.EmployeeSpecialKey;
import com.attendance.www.hr.entitys.FurloughBalance;
import com.attendance.www.hr.entitys.FurloughBalanceExample;
import com.attendance.www.hr.entitys.Holiday;
import com.attendance.www.hr.entitys.HolidayExample;
import com.attendance.www.hr.entitys.Lactation;
import com.attendance.www.hr.entitys.LactationExample;
import com.attendance.www.hr.entitys.LinkAddress;
import com.attendance.www.hr.entitys.LinkAddressExample;
import com.attendance.www.hr.entitys.PunchTime;
import com.attendance.www.hr.entitys.PunchTimeExample;
import com.attendance.www.hr.entitys.Request;
import com.attendance.www.hr.entitys.RequestExample;
import com.attendance.www.hr.entitys.RequestReport;
import com.attendance.www.hr.entitys.RequestReportExample;
import com.attendance.www.hr.entitys.Retroactive;
import com.attendance.www.hr.entitys.RetroactiveExample;
import com.attendance.www.hr.entitys.Role;
import com.attendance.www.hr.entitys.RoleExample;
import com.attendance.www.hr.entitys.SchedulDayExample;
import com.attendance.www.hr.entitys.SchedulDayKey;
import com.attendance.www.hr.entitys.SchedulWeek;
import com.attendance.www.hr.entitys.SchedulWeekExample;
import com.attendance.www.hr.entitys.Special;
import com.attendance.www.hr.entitys.SpecialExample;
import com.attendance.www.hr.entitys.SystemConfigure;
import com.attendance.www.hr.entitys.SystemConfigureExample;
import com.attendance.www.hr.entitys.Task;
import com.attendance.www.hr.entitys.TaskExample;
import com.attendance.www.hr.exception.ResultFaultException;
import com.attendance.www.hr.service.IAccessService;
import com.attendance.www.hr.service.IApprovalService;
import com.attendance.www.hr.service.IAttendanceService;
import com.attendance.www.hr.service.IRestVacationService;
import com.attendance.www.hr.utils.FactorialUtils;
import com.attendance.www.hr.utils.MailUtils;
import com.attendance.www.hr.utils.TimeUtils;
import com.attendance.www.hr.utils.ToolUtils;
import com.zhangkongli.frame.utils.MD5Util;

@Service
public class ApprovalServiceImpl implements IApprovalService {
	@Resource
	private AttendanceExtMapper attendanceExtDao;
	@Resource
	private RetroactiveApprovalExtMapper retroactiveApprovalExtDao;
	@Resource
	private ApprovalRuleMapper approvalRuleDao;
	@Resource
	private RequestMapper requestDao;
	@Resource
	private RoleMapper roleDao;
	@Resource
	private EmployeeRoleMapper employeeRoleDao;
	@Resource
	private EmployeeRoleExtMapper employeeRoleExtDao;
	@Resource
	private RetroactiveMapper retroactiveDao;
	@Resource
	private AttendanceMapper attendanceDao;
	@Resource
	private ApprovalRecordMapper approvalRecordDao;
	@Resource
	private ApprovalRecordExtMapper ApprovalRecordExtDao;
	@Resource
	private RequestApprovalExtMapper reqeustApprovalExtDao;
	@Resource
	private FurloughBalanceMapper furloughBalanceDao;
	@Resource
	private IRestVacationService restVacationService;
	@Resource
	private IAccessService accessService;
	@Resource
	private IAttendanceService attendanceService;
	@Resource
	private EmployeeMapper employeeDao;
	@Resource
	private EmployeeExtMapper employeeExtDao;
	@Resource
	private EmployeeSchedulMapper employeeSchedulDao;
	@Resource
	private PunchTimeMapper punchTimeDao;
	@Resource
	private SchedulDayMapper schedulDayDao;
	@Resource
	private SystemConfigureMapper systemConfigureDao;
	@Resource
	private RequestReportMapper requestReportDao;
	@Resource
	private HolidayMapper holidayDao;
	@Resource
	private LactationMapper lactationDao;
	@Resource
	private SpecialMapper specialDao;
	@Resource
	private EmployeeSpecialMapper employeeSpecialDao;
	@Resource
	private RequestExtMapper requestExtDao;
	@Resource
	private EmployeeSpecialExtMapper employeeSpecialExtDao;
	@Resource
	private RetroactiveExtMapper retroactiveExtDao;
	@Resource
	private LactationExtMapper lactationExtDao;
	@Resource
	private LinkAddressMapper linkAddressDao;
	@Resource
	private DictionaryMapper dictionaryDao;
	@Resource
	private AttendanceReportExtMapper attendanceReportExtDao;
	@Resource
	private AttendanceReportMapper attendanceReportDao;
	@Resource
	private TaskMapper taskDao;
	@Resource
	private SchedulWeekMapper schedulWeekDao;
	@Resource
	private SchedulWeekExtMapper schedulWeekExtDao;

	private Logger log = Logger.getLogger(ApprovalServiceImpl.class);
	/**
	 * 获取补签请求列表
	 */
	@Override
	public RetroactiveApprovalPageBean getRetroactiveApprovalList(RetroactiveApprovalParamBean paramBean,
			Integer employeeId) {
		if (employeeId != null && employeeId != 0) {
			List<Integer> employeeIdList = new ArrayList<Integer>();
			EmployeeRoleExample employeeRoleExample = new EmployeeRoleExample();
			employeeRoleExample.createCriteria().andEmployeeIdEqualTo(employeeId);
			List<EmployeeRole> employeeRoleList = employeeRoleDao.selectByExample(employeeRoleExample);
			for (int i = 0; i < employeeRoleList.size(); i++) {
				employeeIdList.addAll(employeeRoleExtDao
						.selectEmployeeRoleGetEmployeeIdByRoleId(employeeRoleList.get(i).getRoleId()));
			}
			employeeIdList = FactorialUtils.filterEmployeeId(employeeIdList);
			paramBean.setEmployeeIdList(employeeIdList);

			/******* 原查询方式 ******/
			/*
			 * EmployeeRoleExample example = new EmployeeRoleExample();
			 * example.createCriteria().andEmployeeIdEqualTo(employeeId); List<EmployeeRole>
			 * employeeRoleList = employeeRoleDao.selectByExample(example);
			 * if(employeeRoleList==null || employeeRoleList.size()==0){ throw new
			 * ResultFaultException("0_00019"); } List<Integer> roleIds = new
			 * ArrayList<Integer>(); for (EmployeeRole employeeRole : employeeRoleList) {
			 * roleIds.add(employeeRole.getRoleId()); } paramBean.setRoleIdList(roleIds);
			 */
		}
		RetroactiveApprovalPageBean retroactiveApprovalPageBean = new RetroactiveApprovalPageBean();
		retroactiveApprovalPageBean
				.setRetroactiveApprovalList(retroactiveApprovalExtDao.getRetroactiveApprovalList(paramBean));
		retroactiveApprovalPageBean.setPageTotal(retroactiveApprovalExtDao.countOfRetroactiveApproval(paramBean));
		return retroactiveApprovalPageBean;
	}

	/**
	 * 获取补签请求列表
	 */
	@Override
	public RetroactiveApprovalPageBean getRetroactiveApprovalListByRole(RetroactiveApprovalParamBean paramBean,
			Integer employeeId) {
		RetroactiveApprovalPageBean retroactiveApprovalPageBean = new RetroactiveApprovalPageBean();
		List<Integer> employeeList = null;
		if (employeeId != null && employeeId != 0) {
			// 登陆员工ID，查询所属岗位，然后通过岗位查询-岗位下的员工ID
			AttendanceBean attendanceBean = new AttendanceBean();
			attendanceBean.setAttendanceDateStart(paramBean.getRetroactiveStratDate());
			attendanceBean.setAttendanceDateEnd(paramBean.getRetroactiveEndDate());
			List<Integer> roleIdList = attendanceExtDao.getRolrByEmployeeId(attendanceBean, employeeId);
			if (roleIdList != null) {
				employeeList = attendanceExtDao.getEmployeeIdListByRoleId(attendanceBean, employeeId, roleIdList);
				paramBean.setEmployeeIdList(employeeList);
				retroactiveApprovalPageBean
						.setRetroactiveApprovalList(retroactiveApprovalExtDao.getRetroactiveApprovalList(paramBean));
				retroactiveApprovalPageBean
						.setPageTotal(retroactiveApprovalExtDao.countOfRetroactiveApproval(paramBean));
			}
		}
		return retroactiveApprovalPageBean;
	}

	/**
	 * 补签审批操作
	 * 
	 * @param retroactiveApprovalBean
	 * @param employeeId              审批人ID
	 * @return
	 */
	@Override
	public boolean saveRetroactiveApproval(RetroactiveApprovalBean retroactiveApprovalBean, Integer employeeId) {
		// 取得审批人岗位和级别
		EmployeeRoleExample example = new EmployeeRoleExample();
		example.createCriteria().andEmployeeIdEqualTo(employeeId);
		List<EmployeeRole> employeeRoleList = employeeRoleDao.selectByExample(example);
		if (employeeRoleList == null || employeeRoleList.size() == 0) {
			throw new ResultFaultException("10_00003");
		}
		// 取出页面选择的补签信息
		List<Integer> retroactiveIdList = retroactiveApprovalBean.getRetroactiveIdList();
		RetroactiveExample rExample = new RetroactiveExample();
		rExample.createCriteria().andRetroactiveIdIn(retroactiveIdList);
		List<Retroactive> retroactiveList = retroactiveDao.selectByExample(rExample);
		// 判断长度不相等，表示为用户可能撤回申请
		if (retroactiveList.size() != retroactiveIdList.size()) {
			throw new ResultFaultException("10_00007");
		}

		for (Retroactive retroactive : retroactiveList) {
			// 取得审批规则
			ApprovalRule approvalRule = approvalRuleDao.selectByPrimaryKey(retroactive.getApprovalRuleId());

			// 取审批记录
			ApprovalRecordExample approvalExample = new ApprovalRecordExample();
			ApprovalRecordExample.Criteria criteria = approvalExample.createCriteria();
			criteria.andRetroactiveIdEqualTo(retroactive.getRetroactiveId());
			criteria.andEmployeeIdIsNull();
			List<ApprovalRecord> approvalRecordList = approvalRecordDao.selectByExample(approvalExample);
			if (approvalRecordList == null || approvalRecordList.size() == 0) {
				throw new ResultFaultException("10_00004");
			}

			ApprovalRecord approvalRecord = approvalRecordList.get(0);

			// 如果审批驳回，修改审批表和补签表状态，还有考勤表
			if (retroactiveApprovalBean.getApprovalState() == 3) {
				approvalRecord.setApprovalDate(new Date());
				approvalRecord.setEmployeeId(employeeId);
				approvalRecord.setIsApprove(3);
				approvalRecord.setApprovalDescription(retroactiveApprovalBean.getDescription());
				approvalRecord.setUpdateTime(new Date());
				approvalRecordDao.updateByPrimaryKeySelective(approvalRecord);

				retroactive.setApprovalState(retroactiveApprovalBean.getApprovalState());
				retroactive.setUpdateTime(new Date());
				retroactiveDao.updateByPrimaryKeySelective(retroactive);

				// 修改考勤记录 --zx
				Attendance attendance = new Attendance();
				attendance.setAttendanceId(retroactive.getAttendanceId());
				attendance.setIsRepaired(3);// 补签失败
				attendance.setIsApprovaled(3);// 审批拒绝
				attendanceDao.updateByPrimaryKeySelective(attendance);

				// 删除链接linkAddress
				LinkAddressExample laExample = new LinkAddressExample();
				laExample.createCriteria().andRetroactiveIdEqualTo(retroactive.getRetroactiveId());
				linkAddressDao.deleteByExample(laExample);
				Employee employee = employeeDao.selectByPrimaryKey(employeeId);
				// 提醒申请人
				String textPart = "您的补签申请被拒绝<br>审批人：" + employee.getChineseName();
				// 邮件提醒
				this.sendEmailByReject(retroactive.getEmployeeId(), textPart, retroactiveApprovalBean.getDescription());
			}
			// 取得审批人的岗位信息
			Role approvalRole = roleDao.selectByPrimaryKey(approvalRecord.getRoleId());

			// 审核通过
			if (retroactiveApprovalBean.getApprovalState() == 2) {
				// 判断是不是最终审批者
				int seq = approvalRecord.getSep();
				int nextSeq = 0;
				int nextApprovalRoleLevel = 0;
				if (seq == 1 && approvalRule.getTwoApprovalRole() != null) {
					nextSeq = 2;
					nextApprovalRoleLevel = approvalRule.getTwoApprovalRole();
				} else if (seq == 2 && approvalRule.getThreeApprovalRole() != null) {
					nextSeq = 3;
					nextApprovalRoleLevel = approvalRule.getThreeApprovalRole();
				} else if (seq == 3 && approvalRule.getFourApprovalRole() != null) {
					nextSeq = 4;
					nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
				} else if (seq == 4 && approvalRule.getFiveApprovalRole() != null) {
					nextSeq = 5;
					nextApprovalRoleLevel = approvalRule.getFiveApprovalRole();
				}
				// 保存审批结果
				approvalRecord.setApprovalDate(new Date());
				approvalRecord.setEmployeeId(employeeId);
				approvalRecord.setIsApprove(2);
				approvalRecord.setApprovalDescription(retroactiveApprovalBean.getDescription());
				approvalRecord.setUpdateTime(new Date());
				approvalRecordDao.updateByPrimaryKeySelective(approvalRecord);
				// 审批人是最终审批者，修改补签表状态
				if (nextSeq == 0) {
					retroactive.setApprovalState(retroactiveApprovalBean.getApprovalState());
					retroactive.setUpdateTime(new Date());
					retroactiveDao.updateByPrimaryKeySelective(retroactive);

					// 更新考勤记录
					Attendance attendance = attendanceDao.selectByPrimaryKey(retroactive.getAttendanceId());

					// 查看还有没有其他审批中的补签申请
					RetroactiveExample reExample = new RetroactiveExample();
					reExample.createCriteria().andAttendanceIdEqualTo(attendance.getAttendanceId())
							.andApprovalStateEqualTo(1);
					List<Retroactive> reList = retroactiveDao.selectByExample(reExample);
					if (reList != null && reList.size() > 0) {
						attendance.setIsApprovaled(1);// 审批中
						attendance.setIsRepaired(1);
					} else {
						attendance.setIsApprovaled(2);// 审批通过
						attendance.setIsRepaired(2);
					}
					if (StringUtils.isEmpty(attendance.getStartTime())
							&& !StringUtils.isEmpty(retroactive.getStartTime())) {
						attendance.setStartTime(retroactive.getStartTime());
					}
					if (!StringUtils.isEmpty(attendance.getStartTime())
							&& !StringUtils.isEmpty(retroactive.getStartTime())) {
						if (TimeUtils.compareTime(attendance.getStartTime(), retroactive.getStartTime()) > 0) {
							attendance.setStartTime(retroactive.getStartTime());
						}
					}
					if (StringUtils.isEmpty(attendance.getEndTime())
							&& !StringUtils.isEmpty(retroactive.getEndTime())) {
						attendance.setEndTime(retroactive.getEndTime());
					}
					if (!StringUtils.isEmpty(attendance.getEndTime())
							&& !StringUtils.isEmpty(retroactive.getEndTime())) {
						if (TimeUtils.compareTime(attendance.getEndTime(), retroactive.getEndTime()) < 0) {
							attendance.setEndTime(retroactive.getEndTime());
						}
					}
					attendanceDao.updateByPrimaryKeySelective(attendance);

					List<Integer> employeeList = new ArrayList<Integer>();
					employeeList.add(retroactive.getEmployeeId());
					resetAttendance(attendance.getAttendanceDate(), attendance.getAttendanceDate(), employeeList);

					// 删除链接linkAddress
					LinkAddressExample laExample = new LinkAddressExample();
					laExample.createCriteria().andRetroactiveIdEqualTo(retroactive.getRetroactiveId());
					linkAddressDao.deleteByExample(laExample);

					// 插入任务表数据
					// this.insertTaskByParam(attendance.getAttendanceDate(),
					// attendance.getEmployeeId());

				} else {
					// 审批人不是最终审批者，新建下一个审批岗位数据
					// 如果空岗位的情况，继续找下一级审批岗位
					Role resultRole = null;
					if (nextSeq == 2) {
						nextApprovalRoleLevel = approvalRule.getTwoApprovalRole();
						resultRole = getNextApprovalRoleId(approvalRole, nextApprovalRoleLevel,
								approvalRule.getLowestApprovalRole());
						if (resultRole == null) {
							nextSeq = 3;
						}
					}
					if (nextSeq == 3) {
						nextApprovalRoleLevel = approvalRule.getThreeApprovalRole();
						resultRole = getNextApprovalRoleId(approvalRole, nextApprovalRoleLevel,
								approvalRule.getLowestApprovalRole());
						if (resultRole == null) {
							nextSeq = 4;
						}
					}
					if (nextSeq == 4) {
						nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
						resultRole = getNextApprovalRoleId(approvalRole, nextApprovalRoleLevel,
								approvalRule.getLowestApprovalRole());
						if (resultRole == null) {
							nextSeq = 5;
						}
					}
					if (nextSeq == 5) {
						nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
						resultRole = getNextApprovalRoleId(approvalRole, nextApprovalRoleLevel,
								approvalRule.getLowestApprovalRole());
					}
					if (resultRole == null) {
						throw new ResultFaultException("10_00005");
					}
					ApprovalRecord newRecord = new ApprovalRecord();
					newRecord.setRetroactiveId(retroactive.getRetroactiveId());
					newRecord.setRoleId(resultRole.getRoleId());
					newRecord.setCreateTime(new Date());
					newRecord.setSep(nextSeq);
					newRecord.setApprovalDescription(retroactiveApprovalBean.getDescription());
					newRecord.setUpdateTime(new Date());
					approvalRecordDao.insertSelective(newRecord);
				}
			}
		}
		return true;
	}

	/**
	 * 取得申请列表
	 */
	@Override
	public RequestApprovalPageBean getRequestList(RequestApprovalParamBean paramBean, Integer employeeId) {
		RequestApprovalPageBean requestApprovalPageBean = new RequestApprovalPageBean();
		if (employeeId != null && employeeId != 0) {
			List<Integer> employeeIdList = new ArrayList<Integer>();
			EmployeeRoleExample employeeRoleExample = new EmployeeRoleExample();
			employeeRoleExample.createCriteria().andEmployeeIdEqualTo(employeeId);
			List<EmployeeRole> employeeRoleList = employeeRoleDao.selectByExample(employeeRoleExample);
			for (int i = 0; i < employeeRoleList.size(); i++) {
				employeeIdList.addAll(employeeRoleExtDao
						.selectEmployeeRoleGetEmployeeIdByRoleId(employeeRoleList.get(i).getRoleId()));
			}
			employeeIdList = FactorialUtils.filterEmployeeId(employeeIdList);
			if (employeeIdList.size() <= 0) {
				employeeIdList.add(-1);
			}
			paramBean.setEmployeeIdList(employeeIdList);

			/************ 原有查询方式 *************/
			/*
			 * EmployeeRoleExample erExample = new EmployeeRoleExample();
			 * erExample.or().andEmployeeIdEqualTo(employeeId).andThruDateIsNull();
			 * erExample.or().andEmployeeIdEqualTo(employeeId).
			 * andThruDateGreaterThanOrEqualTo(new Date()); List<EmployeeRole>
			 * employeeRoleList = employeeRoleDao.selectByExample(erExample);
			 * 
			 * if(employeeRoleList ==null || employeeRoleList.size()==0){ throw new
			 * ResultFaultException("0_00019"); } List<Integer> roleIdList = new
			 * ArrayList<Integer>(); for (EmployeeRole employeeRole : employeeRoleList) {
			 * roleIdList.add(employeeRole.getRoleId()); }
			 * paramBean.setRoleIdList(roleIdList);
			 */
			/************************************/
		}
		requestApprovalPageBean.setRequestApprovalList(reqeustApprovalExtDao.getRequestApprovalList(paramBean));
		requestApprovalPageBean.setPageTotal(reqeustApprovalExtDao.countRequestApprovalList(paramBean));
		return requestApprovalPageBean;
	}

	@Override
	public RequestApprovalBean getRequestApprovalById(Integer requestId) {
		return reqeustApprovalExtDao.getRequestApprovalById(requestId);
	}

	@Override
	public RequestApprovalPageBean getRequestListByRoleId(RequestApprovalParamBean paramBean, Integer employeeId) {
		RequestApprovalPageBean requestApprovalPageBean = new RequestApprovalPageBean();
		List<Integer> employeeIdList = new ArrayList<Integer>();
		if (employeeId != null && employeeId != 0) {
			EmployeeRoleExample employeeRoleExample = new EmployeeRoleExample();
			employeeRoleExample.createCriteria().andEmployeeIdEqualTo(employeeId);
			List<EmployeeRole> employeeRoleList = employeeRoleDao.selectByExample(employeeRoleExample);
			for (int i = 0; i < employeeRoleList.size(); i++) {
				employeeIdList.addAll(employeeRoleExtDao
						.selectEmployeeRoleGetEmployeeIdByRoleId(employeeRoleList.get(i).getRoleId()));
			}
			employeeIdList = FactorialUtils.filterEmployeeId(employeeIdList);
			if (employeeIdList.size() == 0) {
				requestApprovalPageBean.setRequestApprovalList(new ArrayList<RequestApprovalBean>());
				requestApprovalPageBean.setPageTotal(0);
				return requestApprovalPageBean;
			}
			paramBean.setEmployeeIdList(employeeIdList);
			// 登陆员工ID，查询所属岗位，然后通过岗位查询-岗位下的员工ID
			/*
			 * AttendanceBean attendanceBean = new AttendanceBean();
			 * attendanceBean.setAttendanceDateStart(paramBean.getStartDate());
			 * attendanceBean.setAttendanceDateEnd(paramBean.getEndDate()); List<Integer>
			 * roleIdList = attendanceExtDao.getRolrByEmployeeId(attendanceBean,
			 * employeeId); if (roleIdList.size()>0) { employeeIdList =
			 * attendanceExtDao.getEmployeeIdListByRoleId(attendanceBean,
			 * employeeId,roleIdList); if(employeeIdList.size()==0){
			 * requestApprovalPageBean.setRequestApprovalList(new
			 * ArrayList<RequestApprovalBean>()); requestApprovalPageBean.setPageTotal(0);
			 * return requestApprovalPageBean; }
			 * paramBean.setEmployeeIdList(employeeIdList); }else{
			 * requestApprovalPageBean.setRequestApprovalList(new
			 * ArrayList<RequestApprovalBean>()); requestApprovalPageBean.setPageTotal(0);
			 * return requestApprovalPageBean; }
			 */
		}
		requestApprovalPageBean.setRequestApprovalList(reqeustApprovalExtDao.getRequestApprovalListByRoldId(paramBean));
		requestApprovalPageBean.setPageTotal(reqeustApprovalExtDao.countRequestApprovalListByRoldId(paramBean));
		return requestApprovalPageBean;
	}

	/***********************************
	 * 原审批，未连接BPM系统时，审批代码
	 ***********************************/

	/**
	 * 批量审批
	 * 
	 * @param requestApprovalSaveBean
	 * @param employeeId              审批人ID
	 */
	/*
	 * @Override public void saveApprovalRequestList(RequestApprovalSaveBean
	 * requestApprovalSaveBean, Integer employeeId,boolean isHr) { //取得审批人岗位和级别
	 * EmployeeRoleExample example = new EmployeeRoleExample();
	 * example.createCriteria().andEmployeeIdEqualTo(employeeId); List<EmployeeRole>
	 * employeeRoleList = employeeRoleDao.selectByExample(example);
	 * if(employeeRoleList==null || employeeRoleList.size()==0){ throw new
	 * ResultFaultException("10_00003"); }
	 * 
	 * //取出页面选择的申请信息 List<Integer> ids = requestApprovalSaveBean.getRequestIdList();
	 * RequestExample requestExample = new RequestExample();
	 * requestExample.createCriteria().andRequestIdIn(ids)
	 * .andApprovalStateNotEqualTo(0); List<Request> requestList =
	 * requestDao.selectByExample(requestExample);
	 * 
	 * //是否有撤回验证 if (ids.size()>requestList.size()) { throw new
	 * ResultFaultException("10_00007"); }
	 * 
	 * for (Request request : requestList) { if(request.getApprovalRuleId() ==
	 * null){ throw new ResultFaultException("10_00001"); } // 取得审批规则 ApprovalRule
	 * approvalRule =
	 * approvalRuleDao.selectByPrimaryKey(request.getApprovalRuleId());
	 * 
	 * //HR驳回审批的情况 if(isHr && requestApprovalSaveBean.getApprovalState()==3){
	 * Integer requestType=request.getRequestType(); // 如果已经审批通过了，修改假期余额表 if
	 * (request.getApprovalState() == 2) { if
	 * (requestType==0||requestType==1||requestType==7) { //取得年份 Calendar calendar =
	 * Calendar.getInstance(); calendar.setTime(request.getStartDate()); Integer
	 * thisYear = calendar.get(Calendar.YEAR);
	 * 
	 * FurloughBalance furloughBalance = new FurloughBalance(); RestVacationBean
	 * restVacationBean = new RestVacationBean();
	 * restVacationBean.setStartDate(request.getStartDate()); if
	 * (request.getRequestType() == 7) { restVacationBean.setFurloughType(0);
	 * restVacationBean =
	 * restVacationService.getRestVacationByType(restVacationBean,
	 * request.getEmployeeId()); }else if(request.getRequestType()==0){
	 * restVacationBean.setFurloughType(request.getRequestType()); restVacationBean
	 * = restVacationService.getRestVacationByType(restVacationBean,request.
	 * getEmployeeId()); }else if(request.getRequestType()==1){
	 * restVacationBean.setFurloughType(request.getRequestType()); restVacationBean
	 * = restVacationService.getLastYearYearFurlough(restVacationBean,
	 * request.getEmployeeId()); }
	 * 
	 * 
	 * if (request.getHours() == null) {
	 * 
	 * } else {//只会有hours，按天的不操作余额表 if (request.getRequestType() != 7) {
	 * if(request.getRequestType()==0){
	 * furloughBalance.setBalanceHoursDay(restVacationBean.getRealRestVacation().add
	 * (request.getHours())); }else if(request.getRequestType()==1){ Integer
	 * reportYear=request.getReportYear(); if (reportYear.equals(thisYear)) {//同一年
	 * furloughBalance.setBalanceHoursDay(restVacationBean.getRealRestVacation().add
	 * (request.getHours())); } else {//去年
	 * furloughBalance.setBalanceHoursDay(restVacationBean.
	 * getRealLastYearRestVacation().add(request.getHours())); } } } else {
	 * furloughBalance.setBalanceHoursDay(restVacationBean.getRealRestVacation().
	 * subtract(request.getHours())); } } FurloughBalanceExample
	 * furloughBalanceExample = new FurloughBalanceExample();
	 * FurloughBalanceExample.Criteria furloughBalanceCriteria =
	 * furloughBalanceExample.createCriteria();
	 * furloughBalanceCriteria.andEmployeeIdEqualTo(request.getEmployeeId());
	 * if(request.getRequestType()==7){
	 * furloughBalanceCriteria.andFurloughBalanceTypeEqualTo(0); }else{
	 * furloughBalanceCriteria.andFurloughBalanceTypeEqualTo(request.getRequestType(
	 * )); } if(request.getRequestType()==1&&request.getStartDate()!=null) { int
	 * year = request.getReportYear(); furloughBalance.setYear(year+"");
	 * furloughBalanceCriteria.andYearEqualTo(year+""); }
	 * furloughBalance.setUpdateTime(new Date());
	 * furloughBalanceDao.updateByExampleSelective(furloughBalance,
	 * furloughBalanceExample); } } //取N+1,N+2邮箱地址 List<ApprovalRecordBean> apList =
	 * this.getApprovalRecordInfoById(Integer.toString(request.getRequestId()));
	 * 
	 * //操作报表计算用的“小表”，删除其数据 RequestReportExample requestReportExample = new
	 * RequestReportExample();
	 * requestReportExample.createCriteria().andRequestIdEqualTo(request.
	 * getRequestId());
	 * 
	 * //查询天 // List<RequestReport> rrList =
	 * requestReportDao.selectByExample(requestReportExample); //先删除数据
	 * requestReportDao.deleteByExample(requestReportExample); //查询任务表是否已有数据
	 * TaskExample taskExample = new TaskExample();
	 * taskExample.createCriteria().andEmployeeIdEqualTo(request.getEmployeeId())
	 * .andStateEqualTo(0); List<Task> taskList =
	 * taskDao.selectByExample(taskExample);//查询是否已有数据 Map<Date, Integer>
	 * taskDateMap = new HashMap<>(); for (Task task : taskList) {
	 * taskDateMap.put(task.getTaskDate(), 1); } //再循环日期，重新生成 for (RequestReport
	 * requestReport : rrList) { //插入任务表数据 if
	 * (!taskDateMap.containsKey(requestReport.getRequestReportDate())) {//不包含
	 * this.insertTask(requestReport.getRequestReportDate(),
	 * requestReport.getEmployeeId()); } }
	 * 
	 * ApprovalRecord approvalRecord = new ApprovalRecord();
	 * approvalRecord.setApprovalDate(new Date());
	 * approvalRecord.setApprovalDescription(requestApprovalSaveBean.getDescription(
	 * )); approvalRecord.setCreateTime(new Date());
	 * approvalRecord.setEmployeeId(employeeId); approvalRecord.setIsApprove(3);
	 * approvalRecord.setRequestId(request.getRequestId());
	 * approvalRecord.setUpdateTime(new Date());
	 * approvalRecordDao.insert(approvalRecord);
	 * request.setRequestId(request.getRequestId()); request.setApprovalState(3);
	 * request.setUpdateTime(null);//设置更新时间
	 * requestDao.updateByPrimaryKeySelective(request); List<Integer> employeeIdList
	 * = new ArrayList<Integer>(); employeeIdList.add(request.getEmployeeId());
	 * 
	 * // 更新考勤状态 List<Integer> updateEmployeeIdList=new ArrayList<>();
	 * updateEmployeeIdList.add(request.getEmployeeId());
	 * resetAttendance(request.getStartDate(),request.getEndDate(),
	 * updateEmployeeIdList);
	 * 
	 * //查询HRBP的姓名 Employee empHRBP = employeeDao.selectByPrimaryKey(employeeId);
	 * 
	 * // 删除链接linkAddress //this.deleteLinkAdd(request.getRequestId()); //邮件提醒
	 * //查询初始化表 // SystemConfigure
	 * systemConfigure=systemConfigureDao.selectByPrimaryKey(1); //接收者邮箱（申请人）
	 * Employee employee = employeeDao.selectByPrimaryKey(request.getEmployeeId());
	 * //邮件内容 // SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); String
	 * textPart = null;
	 * 
	 * //给N+1,N+2邮箱发邮件 //计数器 int count = 0; for (int i = 0; i < apList.size(); i++)
	 * { // String emails = apList.get(apList.size()-1-i).getEmail(); String
	 * approvalIds = apList.get(apList.size()-1-i).getApproverIds(); String
	 * requestName = apList.get(apList.size()-1-i).getRequestName(); textPart =
	 * sdf.format(new Date()) +"，" + employee.getChineseName() + "的"+ requestName
	 * +"申请被HRBP："+empHRBP.getChineseName()+"驳回，驳回原因："+requestApprovalSaveBean.
	 * getDescription() +"，请登陆HR考勤管理系统查看。"; // String[] strs=emails.split(",");
	 * String[] strs=approvalIds.split(","); for(int j=0; j<strs.length; j++){ //
	 * String email = strs[j]; String approvalId = strs[j]; textPart ="员工：" +
	 * employee.getChineseName()+"<br>" +
	 * requestName+"申请被HRBP："+empHRBP.getChineseName()+"驳回";
	 * this.sendEmailByReject(Integer.parseInt(approvalId),
	 * textPart,requestApprovalSaveBean.getDescription());
	 * //MailUtils.send(systemConfigure, email, AppConstant.MAIL_TITLE, textPart,
	 * AppConstant.MAIL_ENDING); } count++; if (count==2) { break; } } //给申请人邮箱发邮件
	 * String requestName2 = null; if (apList.size()>0) { requestName2 =
	 * apList.get(0).getRequestName(); }
	 * 
	 * //提醒申请人 textPart =
	 * "您的"+requestName2+"申请被HRBP："+empHRBP.getChineseName()+"驳回";
	 * this.sendEmailByReject(employee.getEmployeeId(),
	 * textPart,requestApprovalSaveBean.getDescription());
	 * //MailUtils.send(systemConfigure, employee.getEmail(),
	 * AppConstant.MAIL_TITLE, textPart, AppConstant.MAIL_ENDING); continue; }
	 * 
	 * //取审批记录 ApprovalRecordExample approvalExample = new ApprovalRecordExample();
	 * ApprovalRecordExample.Criteria criteria = approvalExample.createCriteria();
	 * criteria.andRequestIdEqualTo(request.getRequestId());
	 * criteria.andEmployeeIdIsNull(); List<Integer> roleInList = new
	 * ArrayList<Integer>(); for(EmployeeRole eRole:employeeRoleList) {
	 * roleInList.add(eRole.getRoleId()); } criteria.andRoleIdIn(roleInList);
	 * List<ApprovalRecord> approvalRecordList =
	 * approvalRecordDao.selectByExample(approvalExample);
	 * if(approvalRecordList==null || approvalRecordList.size()==0){ throw new
	 * ResultFaultException("10_00004"); } ApprovalRecord approvalRecord =
	 * approvalRecordList.get(0);
	 * 
	 * //如果审批驳回，修改审批记录和申请表状态 if(requestApprovalSaveBean.getApprovalState()==3){
	 * approvalRecord.setApprovalDate(new Date());
	 * approvalRecord.setEmployeeId(employeeId); approvalRecord.setIsApprove(3);
	 * approvalRecord.setApprovalDescription(requestApprovalSaveBean.getDescription(
	 * )); approvalRecord.setUpdateTime(new Date());
	 * approvalRecordDao.updateByPrimaryKeySelective(approvalRecord);
	 * request.setRequestId(request.getRequestId()); request.setApprovalState(3);
	 * request.setUpdateTime(null);//设置更新时间
	 * requestDao.updateByPrimaryKeySelective(request);
	 * 
	 * // 删除链接linkAddress this.deleteLinkAdd(request.getRequestId());
	 * 
	 * Employee employee=employeeDao.selectByPrimaryKey(employeeId);
	 * 
	 * DictionaryExample dicExample = new DictionaryExample();
	 * dicExample.createCriteria().andDicClsEqualTo("4")
	 * .andDicCdEqualTo(request.getRequestType().toString()); List<Dictionary>
	 * dicList = dictionaryDao.selectByExample(dicExample); //提醒申请人 String textPart
	 * = "您的"+ dicList.get(0).getDicName()+"申请被审批人："+employee.getChineseName()+"拒绝";
	 * this.sendEmailByReject(request.getEmployeeId(),
	 * textPart,requestApprovalSaveBean.getDescription()); } //审批通过 else
	 * if(requestApprovalSaveBean.getApprovalState()==2){ //取得审批人的岗位信息 Role
	 * approvalRole = roleDao.selectByPrimaryKey(approvalRecord.getRoleId());
	 * //判断是不是最终审批者 int seq = approvalRecord.getSep(); int nextSeq = 0; int
	 * nextApprovalRoleLevel = 0; if (approvalRule.getTwoApprovalRole() != null) {
	 * nextSeq = 2; nextApprovalRoleLevel = approvalRule.getTwoApprovalRole();
	 * if(approvalRole.getRoleLevel()>=nextApprovalRoleLevel){
	 * if(approvalRule.getThreeApprovalRole() == null){ nextSeq = 0; } } } if
	 * (approvalRule.getThreeApprovalRole() != null) { nextSeq = 3;
	 * nextApprovalRoleLevel = approvalRule.getThreeApprovalRole();
	 * if(approvalRole.getRoleLevel()>=nextApprovalRoleLevel){
	 * if(approvalRule.getFourApprovalRole() == null){ nextSeq = 0; } } } if
	 * (approvalRule.getFourApprovalRole() != null) { nextSeq = 4;
	 * nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
	 * if(approvalRole.getRoleLevel()>=nextApprovalRoleLevel){
	 * if(approvalRule.getFiveApprovalRole() == null){ nextSeq = 0; } } } if
	 * (approvalRule.getFiveApprovalRole() != null) { nextSeq = 5;
	 * nextApprovalRoleLevel = approvalRule.getFiveApprovalRole();
	 * if(approvalRole.getRoleLevel()>=nextApprovalRoleLevel){ nextSeq = 0; } }
	 * 
	 * //保存审批结果 approvalRecord.setApprovalDate(new Date());
	 * approvalRecord.setEmployeeId(employeeId); approvalRecord.setIsApprove(2);
	 * approvalRecord.setApprovalDescription(requestApprovalSaveBean.getDescription(
	 * )); approvalRecord.setUpdateTime(new Date());
	 * approvalRecordDao.updateByPrimaryKeySelective(approvalRecord);
	 * 
	 * //审批人是最终审批者，修改申请表状态 if(nextSeq==0) { request.setApprovalState(2);
	 * request.setUpdateTime(new Date());
	 * requestDao.updateByPrimaryKeySelective(request); //更新余额表和考勤状态
	 * updateAfterApproval(request);
	 * 
	 * //删除链接linkAddress this.deleteLinkAdd(request.getRequestId());
	 * 
	 * //update，先查询天 RequestReportExample requestReportExample = new
	 * RequestReportExample();
	 * requestReportExample.createCriteria().andRequestIdEqualTo(request.
	 * getRequestId()); List<RequestReport> rrList =
	 * requestReportDao.selectByExample(requestReportExample); //查询任务表是否已有数据
	 * TaskExample taskExample = new TaskExample();
	 * taskExample.createCriteria().andEmployeeIdEqualTo(request.getEmployeeId())
	 * .andStateEqualTo(0); List<Task> taskList =
	 * taskDao.selectByExample(taskExample);//查询是否已有数据 Map<Date, Integer>
	 * taskDateMap = new HashMap<>(); for (Task task : taskList) {
	 * taskDateMap.put(task.getTaskDate(), 1); } //再循环日期，重新生成 for (RequestReport
	 * requestReport : rrList) { //插入任务表数据 if
	 * (!taskDateMap.containsKey(requestReport.getRequestReportDate())) {//不包含
	 * this.insertTask(requestReport.getRequestReportDate(),
	 * requestReport.getEmployeeId()); } }
	 * 
	 * }else{ // 审批人不是最终审批者，新建下一个审批岗位数据 // 如果空岗位的情况，继续找下一级审批岗位 Role resultRole =
	 * null; if (nextSeq == 2 && approvalRule.getTwoApprovalRole()!= null) {
	 * nextApprovalRoleLevel = approvalRule.getTwoApprovalRole(); resultRole =
	 * getNextApprovalRoleId(approvalRole,nextApprovalRoleLevel,approvalRule.
	 * getLowestApprovalRole()); if(resultRole!=null &&
	 * resultRole.getRoleLevel()>nextApprovalRoleLevel){ nextSeq = 3; } } if
	 * (nextSeq == 3 && approvalRule.getThreeApprovalRole()!=null) {
	 * nextApprovalRoleLevel = approvalRule.getThreeApprovalRole();
	 * if(resultRole!=null && resultRole.getRoleLevel()>nextApprovalRoleLevel){
	 * nextSeq = 4; }else{ resultRole =
	 * getNextApprovalRoleId(approvalRole,nextApprovalRoleLevel,approvalRule.
	 * getLowestApprovalRole()); if(resultRole!=null &&
	 * resultRole.getRoleLevel()>nextApprovalRoleLevel){ nextSeq = 4; } }
	 * 
	 * } if (nextSeq == 4 && approvalRule.getFourApprovalRole()!=null) {
	 * nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
	 * if(resultRole!=null && resultRole.getRoleLevel()>nextApprovalRoleLevel){
	 * nextSeq = 5; }else{ resultRole =
	 * getNextApprovalRoleId(approvalRole,nextApprovalRoleLevel,approvalRule.
	 * getLowestApprovalRole()); if(resultRole!=null &&
	 * resultRole.getRoleLevel()>nextApprovalRoleLevel){ nextSeq = 5; } } } if
	 * (nextSeq == 5 && approvalRule.getFiveApprovalRole()!=null) {
	 * nextApprovalRoleLevel = approvalRule.getFiveApprovalRole(); resultRole =
	 * getNextApprovalRoleId(approvalRole,nextApprovalRoleLevel,approvalRule.
	 * getLowestApprovalRole()); } if(resultRole==null){ throw new
	 * ResultFaultException("10_00005"); } ApprovalRecord newRecord = new
	 * ApprovalRecord(); newRecord.setRequestId(approvalRecord.getRequestId());
	 * newRecord.setRoleId(resultRole.getRoleId()); newRecord.setCreateTime(new
	 * Date()); newRecord.setIsApprove(1); newRecord.setSep(nextSeq);
	 * newRecord.setUpdateTime(new Date());
	 * approvalRecordDao.insertSelective(newRecord);
	 * 
	 * // 删除链接linkAddress this.deleteLinkAdd(request.getRequestId()); //邮件提醒
	 * List<ApprovalRecordBean> apList =
	 * this.getApprovalRecordInfoById(Integer.toString(request.getRequestId())); for
	 * (ApprovalRecordBean approvalRecordBean : apList) { if
	 * (approvalRecordBean.getIsApprove()!=null &&
	 * approvalRecordBean.getIsApprove()==1) { Employee emp =
	 * employeeDao.selectByPrimaryKey(request.getEmployeeId()); String[]
	 * strIds=approvalRecordBean.getApproverIds().split(","); String textPart =
	 * "员工："+ emp.getChineseName()
	 * +"的"+approvalRecordBean.getRequestName()+"申请待审批，请及时登陆HR考勤管理系统查看"; for(int
	 * j=0; j<strIds.length; j++){ this.sendEmail(Integer.parseInt(strIds[j]),
	 * textPart, approvalRecordBean.getRequestId(),
	 * approvalRecordBean.getRequestType()); } } } } } } }
	 */
	/****************************************************************************************************/

	/**
	 * 批量审批 -新版本，日期：2018-12-12，将原有审批流程等代码注销
	 * 
	 * @param requestApprovalSaveBean
	 * @param employeeId              审批人ID
	 */
	@Override
	public void saveApprovalRequestList(RequestApprovalSaveBean requestApprovalSaveBean, Integer employeeId,
			boolean isHr) {
		// 取得审批人岗位和级别
		EmployeeRoleExample example = new EmployeeRoleExample();
		example.createCriteria().andEmployeeIdEqualTo(employeeId);
		List<EmployeeRole> employeeRoleList = employeeRoleDao.selectByExample(example);
		if (employeeRoleList == null || employeeRoleList.size() == 0) {
			throw new ResultFaultException("10_00003");
		}

		// 取出页面选择的申请信息
		List<Integer> ids = requestApprovalSaveBean.getRequestIdList();
		RequestExample requestExample = new RequestExample();
		requestExample.createCriteria().andRequestIdIn(ids).andApprovalStateNotEqualTo(0);
		List<Request> requestList = requestDao.selectByExample(requestExample);

		// 是否有撤回验证
		if (ids.size() > requestList.size()) {
			throw new ResultFaultException("10_00007");
		}

		for (Request request : requestList) {
			/*
			 * if(request.getApprovalRuleId() == null){ throw new
			 * ResultFaultException("10_00001"); } // 取得审批规则 ApprovalRule approvalRule =
			 * approvalRuleDao.selectByPrimaryKey(request.getApprovalRuleId());
			 */

			// HR驳回审批的情况
			if (isHr && requestApprovalSaveBean.getApprovalState() == 3) {
				Integer requestType = request.getRequestType();
				// 如果已经审批通过了，修改假期余额表
				if (request.getApprovalState() == 2) {
					if (requestType == 0 || requestType == 1 || requestType == 7) {
						// 取得年份
						Calendar calendar = Calendar.getInstance();
						calendar.setTime(request.getStartDate());
						Integer thisYear = calendar.get(Calendar.YEAR);

						FurloughBalance furloughBalance = new FurloughBalance();
						RestVacationBean restVacationBean = new RestVacationBean();
						restVacationBean.setStartDate(request.getStartDate());
						if (request.getRequestType() == 7) {
							restVacationBean.setFurloughType(0);
							restVacationBean = restVacationService.getRestVacationByType(restVacationBean,
									request.getEmployeeId());
						} else if (request.getRequestType() == 0) {
							restVacationBean.setFurloughType(request.getRequestType());
							restVacationBean = restVacationService.getRestVacationByType(restVacationBean,
									request.getEmployeeId());
						} else if (request.getRequestType() == 1) {
							restVacationBean.setFurloughType(request.getRequestType());
							restVacationBean = restVacationService.getLastYearYearFurlough(restVacationBean,
									request.getEmployeeId());
						}

						if (request.getHours() == null) {

						} else {// 只会有hours，按天的不操作余额表
							if (request.getRequestType() != 7) {
								if (request.getRequestType() == 0) {
									furloughBalance.setBalanceHoursDay(
											restVacationBean.getRealRestVacation().add(request.getHours()));
								} else if (request.getRequestType() == 1) {
									Integer reportYear = request.getReportYear();
									if (reportYear.equals(thisYear)) {// 同一年
										furloughBalance.setBalanceHoursDay(
												restVacationBean.getRealRestVacation().add(request.getHours()));
									} else {// 去年
										furloughBalance.setBalanceHoursDay(
												restVacationBean.getRealLastYearRestVacation().add(request.getHours()));
									}
								}
							} else {
								furloughBalance.setBalanceHoursDay(
										restVacationBean.getRealRestVacation().subtract(request.getHours()));
							}
						}
						FurloughBalanceExample furloughBalanceExample = new FurloughBalanceExample();
						FurloughBalanceExample.Criteria furloughBalanceCriteria = furloughBalanceExample
								.createCriteria();
						furloughBalanceCriteria.andEmployeeIdEqualTo(request.getEmployeeId());
						if (request.getRequestType() == 7) {
							furloughBalanceCriteria.andFurloughBalanceTypeEqualTo(0);
						} else {
							furloughBalanceCriteria.andFurloughBalanceTypeEqualTo(request.getRequestType());
						}
						if (request.getRequestType() == 1 && request.getStartDate() != null) {
							int year = request.getReportYear();
							furloughBalance.setYear(year + "");
							furloughBalanceCriteria.andYearEqualTo(year + "");
						}
						furloughBalance.setUpdateTime(new Date());
						furloughBalanceDao.updateByExampleSelective(furloughBalance, furloughBalanceExample);
					}
				}
				// 取N+1,N+2邮箱地址
				List<ApprovalRecordBean> apList = this
						.getApprovalRecordInfoById(Integer.toString(request.getRequestId()));

				// 操作报表计算用的“小表”，删除其数据
				RequestReportExample requestReportExample = new RequestReportExample();
				requestReportExample.createCriteria().andRequestIdEqualTo(request.getRequestId());

				// 查询天
				// List<RequestReport> rrList =
				// requestReportDao.selectByExample(requestReportExample);
				// 先删除数据
				requestReportDao.deleteByExample(requestReportExample);
				// 查询任务表是否已有数据
				/*
				 * TaskExample taskExample = new TaskExample();
				 * taskExample.createCriteria().andEmployeeIdEqualTo(request.getEmployeeId())
				 * .andStateEqualTo(0); List<Task> taskList =
				 * taskDao.selectByExample(taskExample);//查询是否已有数据 Map<Date, Integer>
				 * taskDateMap = new HashMap<>(); for (Task task : taskList) {
				 * taskDateMap.put(task.getTaskDate(), 1); } //再循环日期，重新生成 for (RequestReport
				 * requestReport : rrList) { //插入任务表数据 if
				 * (!taskDateMap.containsKey(requestReport.getRequestReportDate())) {//不包含
				 * this.insertTask(requestReport.getRequestReportDate(),
				 * requestReport.getEmployeeId()); } }
				 */

				ApprovalRecord approvalRecord = new ApprovalRecord();
				approvalRecord.setApprovalDate(new Date());
				approvalRecord.setApprovalDescription(requestApprovalSaveBean.getDescription());
				approvalRecord.setCreateTime(new Date());
				approvalRecord.setEmployeeId(employeeId);
				approvalRecord.setIsApprove(3);
				approvalRecord.setRequestId(request.getRequestId());
				ApprovalRecordExample approvalRecordExample = new ApprovalRecordExample();
				approvalRecordExample.createCriteria().andRequestIdEqualTo(request.getRequestId());
				List<ApprovalRecord> approvalRecordList = approvalRecordDao.selectByExample(approvalRecordExample);
				if (approvalRecordList.size() > 0) {
					approvalRecord.setSep(approvalRecordList.get(approvalRecordList.size() - 1).getSep() + 1);
				} else {
					approvalRecord.setSep(0);
				}
				approvalRecord.setUpdateTime(new Date());
				approvalRecordDao.insert(approvalRecord);

				request.setRequestId(request.getRequestId());
				request.setApprovalState(3);
				request.setUpdateTime(null);// 设置更新时间
				requestDao.updateByPrimaryKeySelective(request);
				List<Integer> employeeIdList = new ArrayList<Integer>();
				employeeIdList.add(request.getEmployeeId());

				// 更新考勤状态
				List<Integer> updateEmployeeIdList = new ArrayList<>();
				updateEmployeeIdList.add(request.getEmployeeId());
				resetAttendance(request.getStartDate(), request.getEndDate(), updateEmployeeIdList);

				// 查询HRBP的姓名
				Employee empHRBP = employeeDao.selectByPrimaryKey(employeeId);

				// 删除链接linkAddress
				// this.deleteLinkAdd(request.getRequestId());
				// 邮件提醒
				// 查询初始化表
				// SystemConfigure systemConfigure=systemConfigureDao.selectByPrimaryKey(1);
				// 接收者邮箱（申请人）
				Employee employee = employeeDao.selectByPrimaryKey(request.getEmployeeId());
				// 邮件内容
				// SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
				String textPart = null;

				// 给N+1,N+2邮箱发邮件
				/*
				 * //计数器 int count = 0; for (int i = 0; i < apList.size(); i++) { // String
				 * emails = apList.get(apList.size()-1-i).getEmail(); String approvalIds =
				 * apList.get(apList.size()-1-i).getApproverIds(); String requestName =
				 * apList.get(apList.size()-1-i).getRequestName(); textPart = sdf.format(new
				 * Date()) +"，" + employee.getChineseName() + "的"+ requestName
				 * +"申请被HRBP："+empHRBP.getChineseName()+"驳回，驳回原因："+requestApprovalSaveBean.
				 * getDescription() +"，请登陆HR考勤管理系统查看。"; // String[] strs=emails.split(",");
				 * String[] strs=approvalIds.split(","); for(int j=0; j<strs.length; j++){ //
				 * String email = strs[j]; String approvalId = strs[j]; textPart ="员工：" +
				 * employee.getChineseName()+"<br>" +
				 * requestName+"申请被HRBP："+empHRBP.getChineseName()+"驳回";
				 * this.sendEmailByReject(Integer.parseInt(approvalId),
				 * textPart,requestApprovalSaveBean.getDescription());
				 * //MailUtils.send(systemConfigure, email, AppConstant.MAIL_TITLE, textPart,
				 * AppConstant.MAIL_ENDING); } count++; if (count==2) { break; } }
				 */
				// 给申请人邮箱发邮件
				String requestName2 = null;
				if (apList.size() > 0) {
					requestName2 = apList.get(0).getRequestName();
				}

				// 提醒申请人
				textPart = "您的" + requestName2 + "申请被HRBP：" + empHRBP.getChineseName() + "驳回";
				this.sendEmailByReject(employee.getEmployeeId(), textPart, requestApprovalSaveBean.getDescription());
				// MailUtils.send(systemConfigure, employee.getEmail(), AppConstant.MAIL_TITLE,
				// textPart, AppConstant.MAIL_ENDING);
				continue;
			}

			// 取审批记录
			/*
			 * ApprovalRecordExample approvalExample = new ApprovalRecordExample();
			 * ApprovalRecordExample.Criteria criteria = approvalExample.createCriteria();
			 * criteria.andRequestIdEqualTo(request.getRequestId());
			 * criteria.andEmployeeIdIsNull(); List<Integer> roleInList = new
			 * ArrayList<Integer>(); for(EmployeeRole eRole:employeeRoleList) {
			 * roleInList.add(eRole.getRoleId()); } criteria.andRoleIdIn(roleInList);
			 * List<ApprovalRecord> approvalRecordList =
			 * approvalRecordDao.selectByExample(approvalExample);
			 * if(approvalRecordList==null || approvalRecordList.size()==0){ throw new
			 * ResultFaultException("10_00004"); }
			 */
			// ApprovalRecord approvalRecord = approvalRecordList.get(0);

			// 如果审批驳回，修改审批记录和申请表状态
			if (requestApprovalSaveBean.getApprovalState() == 3) {
				/*
				 * approvalRecord.setApprovalDate(new Date());
				 * approvalRecord.setEmployeeId(employeeId); approvalRecord.setIsApprove(3);
				 * approvalRecord.setApprovalDescription(requestApprovalSaveBean.getDescription(
				 * )); approvalRecord.setUpdateTime(new Date());
				 * approvalRecordDao.updateByPrimaryKeySelective(approvalRecord);
				 */
				request.setRequestId(request.getRequestId());
				request.setApprovalState(3);
				request.setUpdateTime(null);// 设置更新时间
				requestDao.updateByPrimaryKeySelective(request);

				// 删除链接linkAddress
				this.deleteLinkAdd(request.getRequestId());

				Employee employee = employeeDao.selectByPrimaryKey(employeeId);

				DictionaryExample dicExample = new DictionaryExample();
				dicExample.createCriteria().andDicClsEqualTo("4").andDicCdEqualTo(request.getRequestType().toString());
				List<Dictionary> dicList = dictionaryDao.selectByExample(dicExample);
				// 提醒申请人
				String textPart = "您的" + dicList.get(0).getDicName() + "申请被审批人：" + employee.getChineseName() + "拒绝";
				this.sendEmailByReject(request.getEmployeeId(), textPart, requestApprovalSaveBean.getDescription());
			}
			// 审批通过
			else if (requestApprovalSaveBean.getApprovalState() == 2) {
				/*
				 * //取得审批人的岗位信息 Role approvalRole =
				 * roleDao.selectByPrimaryKey(approvalRecord.getRoleId()); //判断是不是最终审批者 int seq
				 * = approvalRecord.getSep(); int nextSeq = 0; int nextApprovalRoleLevel = 0; if
				 * (approvalRule.getTwoApprovalRole() != null) { nextSeq = 2;
				 * nextApprovalRoleLevel = approvalRule.getTwoApprovalRole();
				 * if(approvalRole.getRoleLevel()>=nextApprovalRoleLevel){
				 * if(approvalRule.getThreeApprovalRole() == null){ nextSeq = 0; } } } if
				 * (approvalRule.getThreeApprovalRole() != null) { nextSeq = 3;
				 * nextApprovalRoleLevel = approvalRule.getThreeApprovalRole();
				 * if(approvalRole.getRoleLevel()>=nextApprovalRoleLevel){
				 * if(approvalRule.getFourApprovalRole() == null){ nextSeq = 0; } } } if
				 * (approvalRule.getFourApprovalRole() != null) { nextSeq = 4;
				 * nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
				 * if(approvalRole.getRoleLevel()>=nextApprovalRoleLevel){
				 * if(approvalRule.getFiveApprovalRole() == null){ nextSeq = 0; } } } if
				 * (approvalRule.getFiveApprovalRole() != null) { nextSeq = 5;
				 * nextApprovalRoleLevel = approvalRule.getFiveApprovalRole();
				 * if(approvalRole.getRoleLevel()>=nextApprovalRoleLevel){ nextSeq = 0; } }
				 * 
				 * //保存审批结果 approvalRecord.setApprovalDate(new Date());
				 * approvalRecord.setEmployeeId(employeeId); approvalRecord.setIsApprove(2);
				 * approvalRecord.setApprovalDescription(requestApprovalSaveBean.getDescription(
				 * )); approvalRecord.setUpdateTime(new Date());
				 * approvalRecordDao.updateByPrimaryKeySelective(approvalRecord);
				 */

				// 审批人是最终审批者，修改申请表状态
				// if(nextSeq==0)
				// {
				/*
				 * request.setApprovalState(2); request.setUpdateTime(new Date());
				 * requestDao.updateByPrimaryKeySelective(request); //更新余额表和考勤状态
				 * updateAfterApproval(request);
				 * 
				 * //删除链接linkAddress this.deleteLinkAdd(request.getRequestId());
				 */

				// update，先查询天
				/*
				 * RequestReportExample requestReportExample = new RequestReportExample();
				 * requestReportExample.createCriteria().andRequestIdEqualTo(request.
				 * getRequestId()); List<RequestReport> rrList =
				 * requestReportDao.selectByExample(requestReportExample); //查询任务表是否已有数据
				 * TaskExample taskExample = new TaskExample();
				 * taskExample.createCriteria().andEmployeeIdEqualTo(request.getEmployeeId())
				 * .andStateEqualTo(0); List<Task> taskList =
				 * taskDao.selectByExample(taskExample);//查询是否已有数据 Map<Date, Integer>
				 * taskDateMap = new HashMap<>(); for (Task task : taskList) {
				 * taskDateMap.put(task.getTaskDate(), 1); } //再循环日期，重新生成 for (RequestReport
				 * requestReport : rrList) { //插入任务表数据 if
				 * (!taskDateMap.containsKey(requestReport.getRequestReportDate())) {//不包含
				 * this.insertTask(requestReport.getRequestReportDate(),
				 * requestReport.getEmployeeId()); } }
				 */

				// }else{
				// 审批人不是最终审批者，新建下一个审批岗位数据
				// 如果空岗位的情况，继续找下一级审批岗位
				/*
				 * Role resultRole = null; if (nextSeq == 2 &&
				 * approvalRule.getTwoApprovalRole()!= null) { nextApprovalRoleLevel =
				 * approvalRule.getTwoApprovalRole(); resultRole =
				 * getNextApprovalRoleId(approvalRole,nextApprovalRoleLevel,approvalRule.
				 * getLowestApprovalRole()); if(resultRole!=null &&
				 * resultRole.getRoleLevel()>nextApprovalRoleLevel){ nextSeq = 3; } } if
				 * (nextSeq == 3 && approvalRule.getThreeApprovalRole()!=null) {
				 * nextApprovalRoleLevel = approvalRule.getThreeApprovalRole();
				 * if(resultRole!=null && resultRole.getRoleLevel()>nextApprovalRoleLevel){
				 * nextSeq = 4; }else{ resultRole =
				 * getNextApprovalRoleId(approvalRole,nextApprovalRoleLevel,approvalRule.
				 * getLowestApprovalRole()); if(resultRole!=null &&
				 * resultRole.getRoleLevel()>nextApprovalRoleLevel){ nextSeq = 4; } }
				 * 
				 * } if (nextSeq == 4 && approvalRule.getFourApprovalRole()!=null) {
				 * nextApprovalRoleLevel = approvalRule.getFourApprovalRole();
				 * if(resultRole!=null && resultRole.getRoleLevel()>nextApprovalRoleLevel){
				 * nextSeq = 5; }else{ resultRole =
				 * getNextApprovalRoleId(approvalRole,nextApprovalRoleLevel,approvalRule.
				 * getLowestApprovalRole()); if(resultRole!=null &&
				 * resultRole.getRoleLevel()>nextApprovalRoleLevel){ nextSeq = 5; } } } if
				 * (nextSeq == 5 && approvalRule.getFiveApprovalRole()!=null) {
				 * nextApprovalRoleLevel = approvalRule.getFiveApprovalRole(); resultRole =
				 * getNextApprovalRoleId(approvalRole,nextApprovalRoleLevel,approvalRule.
				 * getLowestApprovalRole()); } if(resultRole==null){ throw new
				 * ResultFaultException("10_00005"); } ApprovalRecord newRecord = new
				 * ApprovalRecord(); newRecord.setRequestId(approvalRecord.getRequestId());
				 * newRecord.setRoleId(resultRole.getRoleId()); newRecord.setCreateTime(new
				 * Date()); newRecord.setIsApprove(1); newRecord.setSep(nextSeq);
				 * newRecord.setUpdateTime(new Date());
				 * approvalRecordDao.insertSelective(newRecord);
				 */

				// 删除链接linkAddress
				/*
				 * this.deleteLinkAdd(request.getRequestId()); //邮件提醒 List<ApprovalRecordBean>
				 * apList =
				 * this.getApprovalRecordInfoById(Integer.toString(request.getRequestId())); for
				 * (ApprovalRecordBean approvalRecordBean : apList) { if
				 * (approvalRecordBean.getIsApprove()!=null &&
				 * approvalRecordBean.getIsApprove()==1) { Employee emp =
				 * employeeDao.selectByPrimaryKey(request.getEmployeeId()); String[]
				 * strIds=approvalRecordBean.getApproverIds().split(","); String textPart =
				 * "员工："+ emp.getChineseName()
				 * +"的"+approvalRecordBean.getRequestName()+"申请待审批，请及时登陆HR考勤管理系统查看"; for(int
				 * j=0; j<strIds.length; j++){ this.sendEmail(Integer.parseInt(strIds[j]),
				 * textPart, approvalRecordBean.getRequestId(),
				 * approvalRecordBean.getRequestType()); } } }
				 */
				// }
			}
		}
	}

	/*
	 * 审批通过后，更新相关数据
	 */
	@Override
	public void updateAfterApproval(Request request) {

		saveOrGetRequestMinutes(request, 2);

		// 取得年份
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(request.getStartDate());
		Integer thisYear = calendar.get(Calendar.YEAR);

		if (request.getRequestType() == 7 || request.getRequestType() == 1 || request.getRequestType() == 0) {
			// 添加剩余额度表
			FurloughBalance furloughBalance = new FurloughBalance();
			furloughBalance.setEmployeeId(request.getEmployeeId());
			furloughBalance.setFurloughBalanceType(request.getRequestType());
			if (request.getRequestType() == 7) {
				furloughBalance.setFurloughBalanceType(0);
			}
			RestVacationBean restVacationBean = new RestVacationBean();
			if (request.getRequestType() == 7) {
				restVacationBean.setFurloughType(0);
				restVacationBean = restVacationService.getRestVacationByType(restVacationBean, request.getEmployeeId());
			} else if (request.getRequestType() == 0) {
				restVacationBean.setFurloughType(request.getRequestType());
				restVacationBean.setStartDate(request.getStartDate());
				restVacationBean = restVacationService.getRestVacationByType(restVacationBean, request.getEmployeeId());
			} else if (request.getRequestType() == 1) {
				restVacationBean.setFurloughType(request.getRequestType());
				restVacationBean.setStartDate(request.getStartDate());
				restVacationBean = restVacationService.getLastYearYearFurlough(restVacationBean,
						request.getEmployeeId());
			}

			if (request.getHours() == null) {// 按天申请的，也不会进入判断
				// if(request.getRequestType()==7){
				// furloughBalance.setBalanceHoursDay(restVacationBean.getRealRestVacation().add(new
				// BigDecimal(request.getDayNumber())));
				// }else{
				// furloughBalance.setBalanceHoursDay(restVacationBean.getRealRestVacation().subtract(new
				// BigDecimal(request.getDayNumber())));
				// }
			} else {
				if (request.getRequestType() == 7) {
					furloughBalance.setBalanceHoursDay(restVacationBean.getRealRestVacation().add(request.getHours()));
				} else if (request.getRequestType() == 0) {
					furloughBalance
							.setBalanceHoursDay(restVacationBean.getRealRestVacation().subtract(request.getHours()));
				} else if (request.getRequestType() == 1) {
					Integer reportYear = request.getReportYear();
					if (reportYear.equals(thisYear)) {// 同一年
						furloughBalance.setBalanceHoursDay(
								restVacationBean.getRealRestVacation().subtract(request.getHours()));
					} else {// 去年
						furloughBalance.setBalanceHoursDay(
								restVacationBean.getRealLastYearRestVacation().subtract(request.getHours()));
					}
				}
			}
			FurloughBalanceExample furloughBalanceExample = new FurloughBalanceExample();
			FurloughBalanceExample.Criteria furloughBalanceCriteria = furloughBalanceExample.createCriteria();
			if (request.getRequestType() == 1 && request.getStartDate() != null) {
				// Calendar c = Calendar.getInstance();
				// c.setTime(request.getStartDate());
				// int year = c.get(Calendar.YEAR);
				int year = request.getReportYear();
				furloughBalance.setYear(year + "");
				furloughBalanceCriteria.andYearEqualTo(year + "");
			}
			furloughBalanceCriteria.andEmployeeIdEqualTo(request.getEmployeeId());
			if (request.getRequestType() == 7) {
				furloughBalanceCriteria.andFurloughBalanceTypeEqualTo(0);
			} else {
				furloughBalanceCriteria.andFurloughBalanceTypeEqualTo(request.getRequestType());
			}
			List<FurloughBalance> furloughBalanceList = furloughBalanceDao.selectByExample(furloughBalanceExample);
			if (furloughBalanceList.size() > 0) {
				furloughBalance.setFurloughBalanceId(furloughBalanceList.get(0).getFurloughBalanceId());
				furloughBalance.setUpdateTime(new Date());
				furloughBalanceDao.updateByPrimaryKeySelective(furloughBalance);
			} else {
				//
				furloughBalance.setInitHoursDay(restVacationBean.getTotalVacation());
				furloughBalanceDao.insertSelective(furloughBalance);
			}
		}

		// 如果不是休假类型，跳过后续操作
		if (request.getRequestType() == 7) {
			return;
		}

		// 开始日期
		Date startDate = request.getStartDate();
		// 结束日期
		Date endDate = request.getEndDate();

		// 按分钟计算/按天计算
		boolean isMinute = true;
		if (request.getRequestType() == 3 || request.getRequestType() == 4 || request.getRequestType() == 11
				|| request.getRequestType() == 13) {
			isMinute = false;
		}

		// 重计算
		List<Integer> employeeIdList = new ArrayList<>();
		employeeIdList.add(request.getEmployeeId());
		this.resetAttendance(startDate, endDate, employeeIdList);

	}

	/*
	 * 补签审批通过后，更新相关数据
	 */
	private void updateAfterRetroactiveApproval(Retroactive retroactive) {

		// 考勤数据
		Attendance attendance = attendanceDao.selectByPrimaryKey(retroactive.getAttendanceId());
		Date retroactiveDate = attendance.getAttendanceDate();

		// 取得人员的排班时间
		EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
		employeeSchedulExample.or().andEmployeeIdEqualTo(attendance.getEmployeeId())
				.andFromDateLessThanOrEqualTo(retroactiveDate).andThruDateGreaterThanOrEqualTo(retroactiveDate);
		employeeSchedulExample.or().andEmployeeIdEqualTo(attendance.getEmployeeId())
				.andFromDateLessThanOrEqualTo(retroactiveDate).andThruDateIsNull();
		employeeSchedulExample.setOrderByClause("from_date desc");
		List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
		if (employeeSchedulList == null || employeeSchedulList.size() == 0) {
			// 未找到排班信息
			throw new ResultFaultException("5_00006");
		}
		// 取得打卡时间配置记录
		PunchTime punchTime = punchTimeDao.selectByPrimaryKey(employeeSchedulList.get(0).getPunchTimeId());
		// 取得应出勤时长
		Integer punchMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(), punchTime.getEndFromTime());

		Integer startStatus = 1;
		Integer endStatus = 1;
		String attendanceStime = attendance.getStartTime();
		String attendanceEtime = attendance.getEndTime();
		String stime = "";
		String etime = "";
		if (StringUtils.isEmpty(attendanceStime)) {
			attendanceStime = attendance.getOriginalStartTime();
		}
		if (StringUtils.isEmpty(attendanceEtime)) {
			attendanceEtime = attendance.getOriginalEndTime();
		}

		if (!StringUtils.isEmpty(retroactive.getStartTime())) {
			// 早上签到补签
			if (StringUtils.isEmpty(attendanceStime)) {
				attendanceStime = retroactive.getStartTime();
				;
			} else {
				if (TimeUtils.compareTime(retroactive.getStartTime(), attendanceStime) < 0) {
					attendanceStime = retroactive.getStartTime();
				}
			}
		} else {
			// 晚上签退补签
			if (StringUtils.isEmpty(attendanceEtime)) {
				attendanceEtime = retroactive.getEndTime();
			} else {
				if (TimeUtils.compareTime(attendanceEtime, retroactive.getEndTime()) < 0) {
					attendanceEtime = retroactive.getEndTime();
				}
			}
		}

		if (StringUtils.isEmpty(attendanceStime)) {
			stime = punchTime.getStartFromTime();
		} else {
			if (TimeUtils.compareTime(attendanceStime, punchTime.getStartFromTime()) < 0) {
				stime = punchTime.getStartFromTime();
			} else {
				stime = attendanceStime;
			}
		}

		if (StringUtils.isEmpty(attendanceEtime)) {
			etime = punchTime.getEndToTime();
		} else {
			if (TimeUtils.compareTime(attendanceEtime, punchTime.getEndToTime()) > 0) {
				etime = punchTime.getEndToTime();
			} else {
				etime = attendanceEtime;
			}
		}

		// 取得出勤时长
		Integer tempMinutes = TimeUtils.differMinutes(stime, etime);
		// 出勤时间不够
		if (tempMinutes < punchMinutes) {
			if (TimeUtils.compareTime(punchTime.getStartToTime(), stime) < 0) {
				if (TimeUtils.differMinutes(punchTime.getStartToTime(), stime) > punchTime.getStartInterval()) {
					// 早旷工
					startStatus = 5;
				} else {
					// 早迟到
					startStatus = 2;
				}
			}
			if (TimeUtils.compareTime(punchTime.getEndFromTime(), etime) > 0) {
				if (TimeUtils.differMinutes(etime, punchTime.getEndFromTime()) > punchTime.getEndInterval()) {
					// 晚 旷工
					endStatus = 5;
				} else {
					// 晚 早退
					endStatus = 3;
				}
			}
			if (punchMinutes - tempMinutes > punchTime.getEndInterval()) {
				// 晚 旷工
				endStatus = 5;
			}
		} else {
			// 正常
		}

		if (startStatus == 5 || endStatus == 5) {
			// 旷工
			attendance.setAttendanceState(5);
		} else if (startStatus == 2 && endStatus == 1) {
			// 迟到
			attendance.setAttendanceState(2);
		} else if (startStatus == 1 && endStatus == 3) {
			// 早退
			attendance.setAttendanceState(3);
		} else if (startStatus == 2 && endStatus == 3) {
			// 迟到并早退
			attendance.setAttendanceState(5);
		} else {
			// 正常
			attendance.setAttendanceState(1);
		}
		if (!StringUtils.isEmpty(attendanceStime)) {
			attendance.setStartTime(attendanceStime);
		}
		if (!StringUtils.isEmpty(attendanceEtime)) {
			attendance.setEndTime(attendanceEtime);
		}
		attendance.setUpdateTime(new Date());
		attendance.setIsApprovaled(2);
		attendance.setIsRepaired(2);
		attendanceDao.updateByPrimaryKeySelective(attendance);
	}

	/*
	 * 通过审批人的岗位，取下一级别审批人的岗位 找不到合适的岗位时，返回null
	 */
	@Override
	public Role getNextApprovalRoleId(Role approvalRole, Integer nextApprovalRoleLevel,
			Integer lowestApprovalRoleLevel) {

		// 取所有父级岗位Id
		String rolePath = approvalRole.getRolePath();
		String[] roleIds = reverseArray(rolePath.split("-"));
		List<Integer> roleIdList = new ArrayList<Integer>();
		for (String roleid : roleIds) {
			if (StringUtils.isEmpty(roleid)) {
				continue;
			}
			int intRoleId = Integer.parseInt(roleid);
			// 跳过本人
			if (intRoleId == approvalRole.getRoleId()) {
				continue;
			}
			// 取N+1岗位id
			if (nextApprovalRoleLevel == 99) {
				if (haveEmployeeInRole(intRoleId)) {
					Role nextRole = roleDao.selectByPrimaryKey(intRoleId);
					// 判断最低审批级别
					if (lowestApprovalRoleLevel == null || lowestApprovalRoleLevel <= nextRole.getRoleLevel()) {
						return nextRole;
					} else {
						continue;
					}
				} else {
					// 空岗位跳过
					continue;
				}
			} else {
				roleIdList.add(intRoleId);
			}
		}
		if (roleIdList.size() == 0) {
			throw new ResultFaultException("10_00005");
		}

		// 取指定级别的审批人岗位
		RoleExample roleExample = new RoleExample();
		roleExample.createCriteria().andRoleIdIn(roleIdList);
		roleExample.setOrderByClause("role_level");
		List<Role> roleList = roleDao.selectByExample(roleExample);
		if (roleList == null || roleList.size() == 0) {
			// 没有当前级别的岗位
			return null;
		}
		for (Role role : roleList) {
			// 空岗位
			if (haveEmployeeInRole(role.getRoleId())) {
				return role;
			}
		}
		return null;
	}

	/*
	 * 判断当前岗位是不是空岗位
	 */
	private boolean haveEmployeeInRole(Integer roleId) {
		EmployeeRoleExample example = new EmployeeRoleExample();
		example.or().andRoleIdEqualTo(roleId).andFromDateLessThanOrEqualTo(new Date()).andThruDateIsNull();
		example.or().andRoleIdEqualTo(roleId).andFromDateLessThanOrEqualTo(new Date())
				.andThruDateGreaterThanOrEqualTo(new Date());

		List<EmployeeRole> employeeRoleList = employeeRoleDao.selectByExample(example);
		if (employeeRoleList == null || employeeRoleList.size() == 0) {
			return false;
		}
		List<Integer> employeeIds = new ArrayList<Integer>();
		for (EmployeeRole employeeRole : employeeRoleList) {
			employeeIds.add(employeeRole.getEmployeeId());
		}
		EmployeeExample employeeExample = new EmployeeExample();
		employeeExample.createCriteria().andEmployeeIdIn(employeeIds).andEmployeeIsSeparatedEqualTo(0);

		List<Employee> employeeList = employeeDao.selectByExample(employeeExample);
		if (employeeList == null || employeeList.size() == 0) {
			return false;
		}
		return true;
	}

	/*
	 * 函数：reverseArray 功能：实现 数组翻转 例如：{'a','b','c','d'}变成{'d','c','b','a'}
	 */
	private String[] reverseArray(String[] Array) {
		String[] new_array = new String[Array.length];
		for (int i = 0; i < Array.length; i++) {
			// 反转后数组的第一个元素等于源数组的最后一个元素：
			new_array[i] = Array[Array.length - i - 1];
		}
		return new_array;
	}

	/**
	 * 查询某人申请的审批信息--张鑫
	 */
	@Override
	public List<ApprovalRecordBean> getApprovalRecordInfoById(String requestId) {
		List<ApprovalRecordBean> approvalRecordBeanList = ApprovalRecordExtDao
				.getApprovalRecordInfoByHR(Integer.parseInt(requestId));
		return approvalRecordBeanList;

		// 查询审批节点人员2018-10-12
		// ApprovalRecordExample approvalRecordExample=new ApprovalRecordExample();
		// approvalRecordExample.createCriteria().andRequestIdEqualTo(Integer.parseInt(requestId));
		// approvalRecordExample.setOrderByClause("create_time desc");
		// List<ApprovalRecord>
		// approvalRecordList=approvalRecordDao.selectByExample(approvalRecordExample);
		// if (approvalRecordList.size()>0) {
		// ApprovalRecord approvalRecord=approvalRecordList.get(0);
		// 判断是不是HR驳回
		// if (approvalRecord.getRoleId()==null) {
		// List<ApprovalRecordBean> approvalRecordBeanList =
		// ApprovalRecordExtDao.getApprovalRecordInfoByHR(Integer.parseInt(requestId));
		// return approvalRecordBeanList;
		// }
		// }

		/*
		 * //获取申请记录 Request
		 * request=requestDao.selectByPrimaryKey(Integer.parseInt(requestId));
		 * //获取roleId Integer requestRoleId=request.getRoleId(); //获取审批规则 Integer
		 * approvalRuleId=request.getApprovalRuleId(); ApprovalRule
		 * approvalRule=approvalRuleDao.selectByPrimaryKey(approvalRuleId); Integer
		 * lowestApprovalRoleLevel=null; if (approvalRule.getLowestApprovalRole()!=null)
		 * { lowestApprovalRoleLevel=approvalRule.getLowestApprovalRole(); }
		 * List<Integer> roleLevelList=new ArrayList<>(); if
		 * (approvalRule.getOneApprovalRole()!=null) {
		 * roleLevelList.add(approvalRule.getOneApprovalRole()); if
		 * (approvalRule.getTwoApprovalRole()!=null) {
		 * roleLevelList.add(approvalRule.getTwoApprovalRole()); if
		 * (approvalRule.getThreeApprovalRole()!=null) {
		 * roleLevelList.add(approvalRule.getThreeApprovalRole()); if
		 * (approvalRule.getFourApprovalRole()!=null) {
		 * roleLevelList.add(approvalRule.getFourApprovalRole()); if
		 * (approvalRule.getFiveApprovalRole()!=null) {
		 * roleLevelList.add(approvalRule.getFiveApprovalRole()); } } } } } Integer
		 * nextApprovalRoleLevel=roleLevelList.get(0); //去DB里查的roleID集合 List<Integer>
		 * roleIdDBList=new ArrayList<>();
		 *//**
			 * 获取roleList 岗位集合
			 *//*
				 * Role requestRole=roleDao.selectByPrimaryKey(requestRoleId);
				 * 
				 * 
				 * String rolePath=requestRole.getRolePath(); String[] roleIds =
				 * reverseArray(rolePath.split("-")); List<Integer> roleIdList = new
				 * ArrayList<Integer>(); for (String roleid : roleIds) {
				 * if(StringUtils.isEmpty(roleid)){ continue; } Integer intRoleId =
				 * Integer.parseInt(roleid); //跳过岗位本身 if(intRoleId ==
				 * requestRole.getRoleId().intValue()){ continue; } // 取N+1岗位id if
				 * (nextApprovalRoleLevel == 99) { if(haveEmployeeInRole(intRoleId)){ Role
				 * nextRole = roleDao.selectByPrimaryKey(intRoleId); //判断最低审批级别
				 * if(lowestApprovalRoleLevel == null || lowestApprovalRoleLevel<=
				 * nextRole.getRoleLevel()){ roleIdDBList.add(intRoleId);
				 * List<ApprovalRecordBean> approvalRecordBeanList =
				 * ApprovalRecordExtDao.getApprovalRecordInfoById(Integer.parseInt(requestId),
				 * roleIdDBList, new Date()); return approvalRecordBeanList; }else{ continue; }
				 * }else{ //空岗位跳过 continue; } }else{ roleIdList.add(intRoleId); } } // create
				 * example RoleExample roleExample=new RoleExample();
				 * roleExample.createCriteria().andRoleIdIn(roleIdList);
				 * roleExample.setOrderByClause("role_level asc"); List<Role> roleList =
				 * roleDao.selectByExample(roleExample); //如果审批流中取得的岗位都为空，直接去取本人的父级岗位人审批 if
				 * (roleList.size()==0) { Role nextRole=this.getNextApprovalRoleId(requestRole,
				 * nextApprovalRoleLevel, lowestApprovalRoleLevel);
				 * roleIdDBList.add(nextRole.getRoleId()); List<ApprovalRecordBean>
				 * approvalRecordBeanList=
				 * ApprovalRecordExtDao.getApprovalRecordInfoById(Integer.parseInt(requestId),
				 * roleIdDBList, new Date()); return approvalRecordBeanList; } List<Integer>
				 * roleIdListNeed=new ArrayList<>(); for (int i=0;i<roleLevelList.size();i++) {
				 * for (Role role : roleList) { if(roleLevelList.get(i)==role.getRoleLevel()){
				 * // roleid add list roleIdListNeed.add(role.getRoleId()); } } }
				 * //规则的最终审批人在此人的rolePath中不存在时 boolean isLevel = true; for (Role role :
				 * roleList) {
				 * if(roleLevelList.get(roleLevelList.size()-1)==role.getRoleLevel()){
				 * isLevel=false; break; } } if (isLevel) { Integer roleId=null; for (Role role
				 * : roleList) {
				 * if(role.getRoleLevel()>roleLevelList.get(roleLevelList.size()-1)){
				 * roleId=role.getRoleId(); break; } } roleIdListNeed.add(roleId); }
				 * 
				 * for (Integer roleId : roleIdListNeed) { //判断空岗位，如果不是空岗位，取下面的人
				 * //如果是空岗位，跳过本行（如果是最后一个岗位，找nextrole-for） if(haveEmployeeInRole(roleId)){
				 * roleIdDBList.add(roleId); }else{ //如果是最后一个岗位，找nextrole-for if
				 * (roleId==roleIdListNeed.get(roleIdListNeed.size()-1)) { //rolePath的ID集合 for
				 * (Integer nextRoleId : roleIdList) { Role
				 * nextRole=roleDao.selectByPrimaryKey(nextRoleId); Role
				 * emptyRole=roleDao.selectByPrimaryKey(roleId); if (nextRole.getRoleLevel() >
				 * emptyRole.getRoleLevel()) { if (haveEmployeeInRole(nextRoleId)) {
				 * roleIdDBList.add(nextRoleId); break; } } } } //空岗位跳过 continue; } } //sql
				 * List<ApprovalRecordBean> approvalRecordBeanList=
				 * ApprovalRecordExtDao.getApprovalRecordInfoById(Integer.parseInt(requestId),
				 * roleIdDBList, new Date()); return approvalRecordBeanList;
				 */
	}

	/**
	 * 获取补签结果
	 */
	@Override
	public List<ApprovalRecordBean> getApprovalRecordById(Integer retroactiveId) {
		List<ApprovalRecordBean> approvalRecordBeanList = ApprovalRecordExtDao.getApprovalRecordById(retroactiveId);
		// 查询审批节点人员 2018-10-12
		/*
		 * List<ApprovalRecordBean>
		 * approvalRecordBeanList=ApprovalRecordExtDao.getApprovalRecordById(
		 * retroactiveId); for (ApprovalRecordBean approvalRecordBean :
		 * approvalRecordBeanList) { if (approvalRecordBean.getChineseName()==null) {
		 * Integer roleId=approvalRecordBean.getRoleId(); EmployeeRoleExample
		 * example=new EmployeeRoleExample();
		 * example.or().andRoleIdEqualTo(roleId).andThruDateIsNull();
		 * example.or().andRoleIdEqualTo(roleId).andThruDateGreaterThanOrEqualTo(new
		 * Date()); List<EmployeeRole>
		 * employeeRoleList=employeeRoleDao.selectByExample(example); List<Integer>
		 * employeeIdList=new ArrayList<>(); for (EmployeeRole employeeRole :
		 * employeeRoleList) { employeeIdList.add(employeeRole.getEmployeeId()); }
		 * List<String> employeeNameList=new ArrayList<>(); if(employeeIdList == null ||
		 * employeeIdList.size()==0){ employeeNameList.add("无后续审批人，该流程无法流转！"); }else{
		 * EmployeeExample employeeExample=new EmployeeExample();
		 * employeeExample.createCriteria().andEmployeeIdIn(employeeIdList);
		 * List<Employee> employeeList=employeeDao.selectByExample(employeeExample);
		 * String email = null; String ids = null; for (Employee employee :
		 * employeeList) { employeeNameList.add(employee.getChineseName()); if
		 * (email==null) { email = employee.getEmail(); ids =
		 * Integer.toString(employee.getEmployeeId()); } else { email = email +","+
		 * employee.getEmail(); ids = ids +","+ employee.getEmployeeId(); } }
		 * approvalRecordBean.setEmail(email); approvalRecordBean.setApproverIds(ids); }
		 * approvalRecordBean.setEmployeeNameList(employeeNameList); } }
		 */
		return approvalRecordBeanList;
	}

	/**
	 * 获取多条补签结果
	 */
	@Override
	public List<ApprovalRecordBean> getApprovalRecordByAttendanceId(Integer attendanceId) {
		List<ApprovalRecordBean> recordlist = new ArrayList<ApprovalRecordBean>();
		RetroactiveExample retroactiveExample = new RetroactiveExample();
		retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceId);
		List<Retroactive> retroactiveList = retroactiveDao.selectByExample(retroactiveExample);
		if (retroactiveList.size() > 0) {
			for (int i = 0; i < retroactiveList.size(); i++) {
				List<ApprovalRecordBean> approvalRecordBeanList = this
						.getApprovalRecordById(retroactiveList.get(i).getRetroactiveId());
				for (int j = 0; j < approvalRecordBeanList.size(); j++) {
					recordlist.add(approvalRecordBeanList.get(j));
				}
			}
		}
		return recordlist;
	}

	/**
	 * 计算请假/加班时长
	 */
	public Integer getRequestMinutes(Request request) {
		return saveOrGetRequestMinutes(request, 0);
	}

	/**
	 * 计算加班时长（分钟）
	 */
	private Integer getOverTimeMinutes(Request request, Integer approveStatus) {

		// 开始日期
		Date startDate = request.getStartDate();
		// 结束日期
		Date endDate = request.getEndDate();

		// 时间简单判断
		if (TimeUtils.getMinutes(request.getStartDate(), request.getStartTime(), request.getEndDate(),
				request.getEndTime()) > 1440) {
			// 加班申请时长不能超过24小时
			throw new ResultFaultException("4_00012");
		}

		Integer resultMinutes = 0;

		// 取得当天的考勤数据
		String[] attTimes = getActAttendance(startDate, request.getEmployeeId());
		if (attTimes == null) {
			throw new ResultFaultException("4_00017");
		}
		String stime = attTimes[0];
		String etime = attTimes[1];
		if (StringUtils.isEmpty(stime) && !StringUtils.isEmpty(etime)) {
			// 考勤信息不完整
			throw new ResultFaultException("4_00014");
		}
		if (!StringUtils.isEmpty(stime) && StringUtils.isEmpty(etime)) {
			// 考勤信息不完整
			throw new ResultFaultException("4_00014");
		}
		if (StringUtils.isEmpty(stime) && StringUtils.isEmpty(etime)) {
			throw new ResultFaultException("4_00017");
		}

		// 判断考勤跨天
		boolean oneday = true;
		if (startDate.before(endDate)) {
			oneday = false;
		}

		if (oneday) {

			// 取得人员的排班时间
			EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
			employeeSchedulExample.or().andEmployeeIdEqualTo(request.getEmployeeId())
					.andFromDateLessThanOrEqualTo(startDate).andThruDateGreaterThanOrEqualTo(startDate);
			employeeSchedulExample.or().andEmployeeIdEqualTo(request.getEmployeeId())
					.andFromDateLessThanOrEqualTo(startDate).andThruDateIsNull();
			employeeSchedulExample.setOrderByClause("from_date Desc");
			List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
			if (employeeSchedulList == null || employeeSchedulList.size() == 0) {
				// 未找到排班信息
				throw new ResultFaultException("5_00006");
			}

			// 取得打卡时间配置记录
			PunchTime punchTime = punchTimeDao.selectByPrimaryKey(employeeSchedulList.get(0).getPunchTimeId());
			// 取得应出勤时长
			Integer punchMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(), punchTime.getEndFromTime());
			// 平时加班要判断加班扣除时间点
			String beginTime = this.getOverTime(startDate);

			// 申请时间和打卡时间取交集
			String resStartTime = stime;
			String resEndTime = etime;
			if (TimeUtils.compareTime(stime, request.getStartTime()) < 0) {
				resStartTime = request.getStartTime();
			}
			if (TimeUtils.compareTime(stime, etime) > 0
					&& TimeUtils.compareTime(request.getStartTime(), request.getEndTime()) <= 0) {
				resEndTime = request.getEndTime();
			}
			if (TimeUtils.compareTime(stime, etime) < 0
					&& TimeUtils.compareTime(request.getStartTime(), request.getEndTime()) < 0) {
				if (TimeUtils.compareTime(etime, request.getEndTime()) > 0) {
					resEndTime = request.getEndTime();
				}
			}

			// 判断是否是休息日
			SchedulDayExample sdExample = new SchedulDayExample();
			sdExample.createCriteria().andSdDateEqualTo(startDate).andSwIdEqualTo(employeeSchedulList.get(0).getSwId());
			List<SchedulDayKey> schedulDayList = schedulDayDao.selectByExample(sdExample);
			// 如果没查到数据，证明是休息日加班。
			if (schedulDayList == null || schedulDayList.size() == 0) {
				// 节假日加班
				if (request.getOvertimeInterval() == null) {
					resultMinutes = TimeUtils.differMinutes(resStartTime, resEndTime);
				} else {
					resultMinutes = TimeUtils.differMinutes(resStartTime, resEndTime) - request.getOvertimeInterval();
				}
				updateRequestReport(request, approveStatus, startDate, new BigDecimal(resultMinutes), 1);
				return resultMinutes;
			}

			// 平时加班
			String accEndTime = getAttendanceEndTime(startDate, request.getEmployeeId());
			if (StringUtils.isEmpty(accEndTime)) {
				throw new ResultFaultException("4_00017");
			}
			if (TimeUtils.compareTime(accEndTime, resStartTime) > 0) {
				throw new ResultFaultException("4_00009");
			}
			if (TimeUtils.compareTime(accEndTime, resStartTime) < 0) {
				accEndTime = resStartTime;
			}
			if (TimeUtils.compareTime(accEndTime, beginTime) < 0 && TimeUtils.compareTime(resEndTime, beginTime) >= 0) {
				resultMinutes = TimeUtils.differMinutes(accEndTime, resEndTime) - 30;
			} else {
				resultMinutes = TimeUtils.differMinutes(accEndTime, resEndTime);
			}

			updateRequestReport(request, approveStatus, startDate, new BigDecimal(resultMinutes), 3);
			return resultMinutes;
		} else {
			// 跨天

			// 取得人员的排班时间
			EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
			employeeSchedulExample.or().andEmployeeIdEqualTo(request.getEmployeeId())
					.andFromDateLessThanOrEqualTo(startDate).andThruDateGreaterThanOrEqualTo(startDate);
			employeeSchedulExample.or().andEmployeeIdEqualTo(request.getEmployeeId())
					.andFromDateLessThanOrEqualTo(startDate).andThruDateIsNull();
			employeeSchedulExample.setOrderByClause("from_date desc");
			List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
			if (employeeSchedulList == null || employeeSchedulList.size() == 0) {
				// 未找到排班信息
				throw new ResultFaultException("5_00006");
			}

			// 取得打卡时间配置记录
			PunchTime punchTime = punchTimeDao.selectByPrimaryKey(employeeSchedulList.get(0).getPunchTimeId());
			// 取得应出勤时长
			Integer punchMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(), punchTime.getEndFromTime());
			// 平时加班要判断加班扣除时间点
			String beginTime = this.getOverTime(startDate);

			// 申请时间和打卡时间取交集
			String resStartTime = stime;
			String resEndTime = etime;
			if (TimeUtils.compareTime(stime, request.getStartTime()) < 0) {
				resStartTime = request.getStartTime();
			}
			if (TimeUtils.compareTime(etime, request.getEndTime()) > 0) {
				resEndTime = request.getEndTime();
			}

			// 判断是否是休息日
			SchedulDayExample sdExample = new SchedulDayExample();
			sdExample.createCriteria().andSdDateEqualTo(startDate).andSwIdEqualTo(employeeSchedulList.get(0).getSwId());
			List<SchedulDayKey> schedulDayList = schedulDayDao.selectByExample(sdExample);
			if (schedulDayList == null || schedulDayList.size() == 0) {
				// 节假日加班
				if (request.getOvertimeInterval() == null) {
					resultMinutes = TimeUtils.getMinutes(startDate, resStartTime, endDate, resEndTime);
				} else {
					resultMinutes = TimeUtils.getMinutes(startDate, resStartTime, endDate, resEndTime)
							- request.getOvertimeInterval();
				}
				updateRequestReport(request, approveStatus, startDate, new BigDecimal(resultMinutes), 1);
				return resultMinutes;
			}

			// 平时加班
			String accEndTime = getAttendanceEndTime(startDate, request.getEmployeeId());
			if (StringUtils.isEmpty(accEndTime)) {
				throw new ResultFaultException("4_00017");
			}
			if (TimeUtils.compareTime(accEndTime, resStartTime) > 0) {
				throw new ResultFaultException("4_00009");
			}
			if (TimeUtils.compareTime(accEndTime, resStartTime) < 0) {
				accEndTime = resStartTime;
			}

			if (TimeUtils.compareTime(accEndTime, beginTime) < 0) {
				resultMinutes = TimeUtils.getMinutes(startDate, accEndTime, endDate, resEndTime) - 30;
			} else {
				resultMinutes = TimeUtils.getMinutes(startDate, accEndTime, endDate, resEndTime);
			}
			updateRequestReport(request, approveStatus, startDate, new BigDecimal(resultMinutes), 3);
			return resultMinutes;
		}
	}

	/**
	 * 计算请假时长（小时，两位小数）--张鑫
	 */
	@Override
	public Integer getRequestMinutes(RequestBean requestBean) {
		Request request = new Request();
		request.setStartDate(requestBean.getStartDate());
		request.setEndDate(requestBean.getEndDate());
		request.setStartTime(requestBean.getStartTime());
		request.setEndTime(requestBean.getEndTime());
		request.setEmployeeId(requestBean.getEmployeeId());
		request.setStartToTime(requestBean.getStartToTime());
		request.setRequestType(requestBean.getRequestType());
		Integer resultMinutes = this.getRequestMinutes(request);
		return resultMinutes;
	}

	/**
	 * 根据夏令冬令时间切换加班时间
	 * 
	 * @param date
	 * @return
	 */
	public String getOverTime(Date date) {
		SystemConfigureExample systemConfigureExample = new SystemConfigureExample();
		List<SystemConfigure> systemConfigures = systemConfigureDao.selectByExample(systemConfigureExample);
		if (systemConfigures == null || systemConfigures.size() == 0) {
			throw new ResultFaultException("0_00030");
		}
		SystemConfigure sysconfig = systemConfigures.get(0);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		int month = calendar.get(Calendar.MONTH);
		if (month >= 4 && month <= 9) {
			return sysconfig.getOverAfterTime();
		} else {
			return sysconfig.getOverBeforeTime();
		}
	}

	/**
	 * 计算请假/加班时长 更新统计用的申请时长基础表 2：审批通过，插入数据；3：审批拒绝，删除数据
	 */
	private Integer saveOrGetRequestMinutes(Request request, Integer approveStatus) {

		// 时间简单判断
		if (request.getRequestType() == 3 || request.getRequestType() == 4 || request.getRequestType() == 11) {
			// 正常
		} else {
			if (TimeUtils.compareDateTime(request.getStartDate(), request.getStartTime(), request.getEndDate(),
					request.getEndTime()) >= 0) {
				// 结束时间必须大于开始时间
				throw new ResultFaultException("4_00018");
			}
		}

		// 加班的情况
		if (request.getRequestType() == 7) {
			//
			if (request.getOvertimeType() != null && request.getOvertimeType() == 4) {// 早上加班
				updateRequestReport(request, approveStatus, request.getStartDate(), request.getHours(), 3);
				return request.getHours().intValue();
			} else {
				return getOverTimeMinutes(request, approveStatus);
			}
		}

		// 计算时，是否考虑休息日
		boolean includeWeekDay = false;
		if (request.getRequestType() == 0 || request.getRequestType() == 1 || request.getRequestType() == 5
				|| request.getRequestType() == 6) {// 事假、年假、病假
			includeWeekDay = true;
		}

		// 按天计算
		boolean isByDay = false;
		if (request.getRequestType() == 3 || request.getRequestType() == 4 || request.getRequestType() == 11
				|| request.getRequestType() == 13) {
			isByDay = true;
		}

		// 开始日期
		Date startDate = request.getStartDate();
		// 结束日期
		Date endDate = request.getEndDate();

		// 按天计算的情况
		if (isByDay) {
			// 控制循环用的
			int resultDay = 0;
			Date tempDate = DateUtils.addDays(startDate, -1);
			while (tempDate.compareTo(endDate) < 0) {
				tempDate = DateUtils.addDays(tempDate, 1);
				resultDay = resultDay + 1;
				updateRequestReport(request, approveStatus, tempDate, new BigDecimal(1), 3);
			}
			return resultDay;
		}

		Integer resultMinutes = 0;
		if (startDate.compareTo(endDate) == 0) {
			// 一天内的请假
			// 取得人员的排班时间
			EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
			employeeSchedulExample.or().andEmployeeIdEqualTo(request.getEmployeeId())
					.andFromDateLessThanOrEqualTo(startDate).andThruDateGreaterThanOrEqualTo(startDate);
			employeeSchedulExample.or().andEmployeeIdEqualTo(request.getEmployeeId())
					.andFromDateLessThanOrEqualTo(startDate).andThruDateIsNull();
			employeeSchedulExample.setOrderByClause("from_date Desc");
			List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
			if (employeeSchedulList == null || employeeSchedulList.size() == 0) {
				// 未找到排班信息
				throw new ResultFaultException("5_00006");
			}

			// 获取班次
			employeeSchedulExample = new EmployeeSchedulExample();
			employeeSchedulExample.createCriteria().andEmployeeIdEqualTo(request.getEmployeeId());
			employeeSchedulExample.setOrderByClause("from_date desc");
			List<EmployeeSchedul> esList = employeeSchedulDao.selectByExample(employeeSchedulExample);
			// 计算是否为无规律班次
			if (employeeSchedulList.size() > 0) {
				Date date = startDate;
				List<EmployeeSchedul> list = esList.stream().filter(s -> s.getFromDate().equals(date))
						.collect(Collectors.toList());
				if (list.size() > 0) {
					employeeSchedulList = new ArrayList<EmployeeSchedul>();
					employeeSchedulList.add(list.get(0));
				}
			}

			// 考虑休息日的情况
			if (includeWeekDay) {
				SchedulDayExample sdExample = new SchedulDayExample();
				sdExample.createCriteria().andSdDateEqualTo(startDate)
						.andSwIdEqualTo(employeeSchedulList.get(0).getSwId());
				List<SchedulDayKey> schedulDayList = schedulDayDao.selectByExample(sdExample);
				// 如果没查到数据，证明不上班。
				if (schedulDayList == null || schedulDayList.size() == 0) {
					return 0;
				}
			}

			// 取得当天的考勤数据
			Attendance attendance = null;
			AttendanceExample attendanceExample = new AttendanceExample();
			AttendanceExample.Criteria attendanceCriteria = attendanceExample.createCriteria();
			attendanceCriteria.andAttendanceDateEqualTo(startDate);
			attendanceCriteria.andEmployeeIdEqualTo(request.getEmployeeId());
			List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);
			if (attendanceList != null && attendanceList.size() > 0) {
				attendance = attendanceList.get(0);
				if (StringUtils.isEmpty(attendance.getStartTime())) {
					attendance = null;
				}
			}

			// 取得打卡时间配置记录
			PunchTime punchTime = punchTimeDao.selectByPrimaryKey(employeeSchedulList.get(0).getPunchTimeId());
			// 取得午休时长
			Integer restMinutes = 0;
			if (punchTime.getRestFromTime() != null && punchTime.getRestToTime() != null) {
				restMinutes = TimeUtils.differMinutes(punchTime.getRestFromTime(), punchTime.getRestToTime());
			}

			// 是否为跨天申请
			boolean punchMinutesType = true;
			// 判断是否为跨天班次
			if (TimeUtils.compareTime(punchTime.getStartFromTime(), punchTime.getEndFromTime()) == 1) {
				restMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(), "23:59");
				punchMinutesType = false;
			}

			// Integer restMinutes = TimeUtils.differMinutes(punchTime.getRestFromTime(),
			// punchTime.getRestToTime());
			// 取得应出勤时长
			Integer punchMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(), punchTime.getEndFromTime());

			String requestStartTime = request.getStartTime();
			String requestEndTime = request.getEndTime();

			if (punchMinutesType) {
				if (TimeUtils.compareTime(requestStartTime, punchTime.getStartFromTime()) < 0) {
					requestStartTime = punchTime.getStartFromTime();
				}
				if (TimeUtils.compareTime(requestEndTime, punchTime.getEndToTime()) > 0) {
					requestEndTime = punchTime.getEndToTime();
				}

				if (attendance != null) {
					String attendanceStartTime = attendance.getStartTime();
					if (TimeUtils.compareTime(attendanceStartTime, punchTime.getStartFromTime()) < 0) {
						attendanceStartTime = punchTime.getStartFromTime();
					}
					// 计算出的下班时间
					String etime = TimeUtils.getEndTime(attendanceStartTime, punchMinutes);
					if (TimeUtils.compareTime(requestEndTime, etime) > 0) {
						// requestEndTime = etime;
					}
				} else {
					// 计算出的下班时间
					String etime = TimeUtils.getEndTime(requestStartTime, punchMinutes);
					if (TimeUtils.compareTime(requestEndTime, etime) > 0) {
						requestEndTime = etime;
					}
				}
			}

			resultMinutes = getMinutesRemoveRest(requestStartTime, requestEndTime, punchTime);
			if (resultMinutes > punchMinutes - restMinutes) {
				resultMinutes = punchMinutes - restMinutes;
			}
			// 时间统计基础记录
			updateRequestReport(request, approveStatus, startDate, new BigDecimal(resultMinutes), 3);

		} else {
			// 跨天

			// 控制循环用的
			Date tempDate = DateUtils.addDays(new Date(startDate.getTime()), -1);

			while (tempDate.compareTo(endDate) < 0) {
				tempDate = DateUtils.addDays(tempDate, 1);
				// 取得人员的排班时间
				EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
				employeeSchedulExample.or().andEmployeeIdEqualTo(request.getEmployeeId())
						.andFromDateLessThanOrEqualTo(tempDate).andThruDateGreaterThanOrEqualTo(tempDate);
				employeeSchedulExample.or().andEmployeeIdEqualTo(request.getEmployeeId())
						.andFromDateLessThanOrEqualTo(tempDate).andThruDateIsNull();
				employeeSchedulExample.setOrderByClause("from_date desc");
				List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
				if (employeeSchedulList == null || employeeSchedulList.size() == 0) {
					// 未找到排班信息
					throw new ResultFaultException("5_00006");
				}

				// 获取班次
				employeeSchedulExample = new EmployeeSchedulExample();
				employeeSchedulExample.createCriteria().andEmployeeIdEqualTo(request.getEmployeeId());
				employeeSchedulExample.setOrderByClause("from_date desc");
				List<EmployeeSchedul> esList = employeeSchedulDao.selectByExample(employeeSchedulExample);
				// 计算是否为无规律班次
				if (employeeSchedulList.size() > 0) {
					Date date = tempDate;
					List<EmployeeSchedul> list = esList.stream().filter(s -> s.getFromDate().equals(date))
							.collect(Collectors.toList());
					if (list.size() > 0) {
						employeeSchedulList = new ArrayList<EmployeeSchedul>();
						employeeSchedulList.add(list.get(0));
					} else {
						// 减一天并且查询该日期是否为跨天考勤
						Date date1 = TimeUtils.getMinusDay(tempDate);
						list = esList.stream().filter(s -> s.getFromDate().equals(date1)).collect(Collectors.toList());
						if (list.size() > 0) {
							employeeSchedulList = new ArrayList<EmployeeSchedul>();
							employeeSchedulList.add(list.get(0));
							request.setStartTime("00:00");
						}
					}
				}

				// 考虑休息日的情况
				if (includeWeekDay) {
					SchedulDayExample sdExample = new SchedulDayExample();
					sdExample.createCriteria().andSdDateEqualTo(tempDate)
							.andSwIdEqualTo(employeeSchedulList.get(0).getSwId());
					List<SchedulDayKey> schedulDayList = schedulDayDao.selectByExample(sdExample);
					// 如果没查到数据，证明不上班。
					if (schedulDayList == null || schedulDayList.size() == 0) {
						continue;
					}
				}

				// 取得打卡时间配置记录
				PunchTime punchTime = punchTimeDao.selectByPrimaryKey(employeeSchedulList.get(0).getPunchTimeId());
				// 取得午休时长
				Integer restMinutes = 0;
				if (punchTime.getRestFromTime() != null && punchTime.getRestToTime() != null) {
					restMinutes = TimeUtils.differMinutes(punchTime.getRestFromTime(), punchTime.getRestToTime());
				}
				// Integer restMinutes = TimeUtils.differMinutes(punchTime.getRestFromTime(),
				// punchTime.getRestToTime());
				// 取得应出勤时长
				Integer punchMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(),
						punchTime.getEndFromTime());

				// 是否为跨天申请
				boolean punchMinutesType = true;
				// 判断是否为跨天班次
				if (TimeUtils.compareTime(punchTime.getStartFromTime(), punchTime.getEndFromTime()) == 1) {
					punchMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(), "23:59");
					punchMinutesType = false;
				}

				// 第一天时长计算
				if (tempDate.compareTo(startDate) == 0) {

					// 取得当天的考勤数据
					Attendance attendance = null;
					AttendanceExample attendanceExample = new AttendanceExample();
					AttendanceExample.Criteria attendanceCriteria = attendanceExample.createCriteria();
					attendanceCriteria.andAttendanceDateEqualTo(tempDate);
					attendanceCriteria.andEmployeeIdEqualTo(request.getEmployeeId());
					List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);
					if (attendanceList != null && attendanceList.size() > 0) {
						attendance = attendanceList.get(0);
						if (StringUtils.isEmpty(attendance.getStartTime())) {
							attendance = null;
						}
					}

					String stime = request.getStartTime();
					String etime = request.getStartToTime();

					if (punchMinutesType) {
						// 根据应出勤时间计算
						if (TimeUtils.compareTime(stime, punchTime.getStartFromTime()) < 0) {
							stime = punchTime.getStartFromTime();
						}

						// 存在打卡记录
						if (attendance != null) {
							// 计算当天的应签退时间
							String attendanceStartTime = attendance.getStartTime();
							if (TimeUtils.compareTime(attendanceStartTime, punchTime.getStartFromTime()) < 0) {
								attendanceStartTime = punchTime.getStartFromTime();
							}
							etime = TimeUtils.getEndTime(attendanceStartTime, punchMinutes);
							if (TimeUtils.compareTime(etime, punchTime.getEndToTime()) > 0) {
								etime = punchTime.getEndToTime();
							}
						} else {
							if (!StringUtils.isEmpty(etime)) {
								if (TimeUtils.compareTime(etime, punchTime.getEndToTime()) > 0) {
									etime = punchTime.getEndToTime();
								}
							} else {
								etime = punchTime.getEndToTime();
							}
						}
					}

					// 考虑午休的情况
					resultMinutes = getMinutesRemoveRest(stime, etime, punchTime);
					if (resultMinutes > punchMinutes - restMinutes) {
						resultMinutes = punchMinutes - restMinutes;
					}

					// 时间统计基础记录
					updateRequestReport(request, approveStatus, tempDate, new BigDecimal(resultMinutes), 3);
				}
				// 中间天的时长
				if (tempDate.compareTo(startDate) != 0 && tempDate.compareTo(endDate) != 0) {
					// 考虑午休的情况
					Integer tempMinutes = punchMinutes - restMinutes;
					// 时间统计基础记录
					updateRequestReport(request, approveStatus, tempDate, new BigDecimal(tempMinutes), 3);
					resultMinutes += tempMinutes;
				}
				// 最后一天的时长
				if (tempDate.compareTo(endDate) == 0) {

					// 配置的开始时间作为当天开始时间
					String stime = request.getStartTime();
					String etime = request.getEndTime();

					if (punchMinutesType) {
						stime = punchTime.getStartFromTime();
						etime = request.getEndTime();

						if (TimeUtils.compareTime(stime, etime) >= 0) {
							// 没到工作时间
							continue;
						}
						if (TimeUtils.compareTime(etime, punchTime.getEndFromTime()) >= 0) {
							etime = punchTime.getEndFromTime();
						}
					}

					// 考虑午休的情况
					Integer tempMinutes = getMinutesRemoveRest(stime, etime, punchTime);
					if (!punchMinutesType) {
						tempMinutes = TimeUtils.differMinutes(stime, etime);
					} else {
						if (tempMinutes > punchMinutes - restMinutes) {
							tempMinutes = punchMinutes - restMinutes;
						}
					}

					// 时间统计基础记录
					updateRequestReport(request, approveStatus, tempDate, new BigDecimal(tempMinutes), 3);
					resultMinutes += tempMinutes;
				}
			}
		}
		return resultMinutes;
	}

	/**
	 * 更新报表计算用的数据
	 * 
	 * @param request
	 * @param approveStatus
	 * @param curDate
	 * @param resultMinutes
	 */
	private void updateRequestReport(Request request, Integer approveStatus, Date curDate, BigDecimal resultMinutes,
			Integer overType) {
		// 时间统计基础记录
		if (approveStatus == 2) {
			// 判断当天是不是节假日
			int dayType = 3;// 平时加班
			if (overType == 3) {
				dayType = overType;
			} else {
				HolidayExample holidayExample = new HolidayExample();
				holidayExample.createCriteria().andHolidayDateEqualTo(curDate);
				List<Holiday> holidayList = holidayDao.selectByExample(holidayExample);
				if (holidayList == null || holidayList.size() == 0) {
					dayType = 2;// 周末加班
				} else {
					Holiday ho = holidayList.get(0);
					if (ho.getIsLegal() == 1) {
						dayType = 1;// 法定加班
					} else {
						dayType = 2;// 周末加班
					}
				}
			}
			RequestReport requestReport = new RequestReport();
			requestReport.setCreateTime(new Date());
			requestReport.setEmployeeId(request.getEmployeeId());
			requestReport.setHours(resultMinutes);
			requestReport.setReportType(request.getRequestType());
			if (request.getRequestType() == 7) {
				requestReport.setOvertimeType(dayType);
				if (request.getOvertimeType() == 4) {// 早上加班
					requestReport.setOvertimeType(4);
				}
			}
			if (request.getRequestType() == 1) {// 年假添加年份
				requestReport.setReportYear(request.getReportYear());
			}
			requestReport.setRequestId(request.getRequestId());
			requestReport.setRequestReportDate(curDate);
			requestReport.setUpdateTime(new Date());
			requestReportDao.insertSelective(requestReport);
		}
		if (approveStatus == 3) {
			RequestReportExample requestReportExample = new RequestReportExample();
			requestReportExample.createCriteria().andRequestIdEqualTo(request.getRequestId())
					.andRequestReportDateEqualTo(curDate);
			requestReportDao.deleteByExample(requestReportExample);
		}
	}

	/**
	 * 重新计算考勤状态
	 * 
	 * @param curDate
	 * @param employeeId
	 */
	@Override
	public void resetAttendance(Date startDates, Date endDates, List<Integer> employeeIdLists) {
		try {
			
		// 删除多余考勤数据
		accessService.deleteAttendance();
		
		String year = ToolUtils.dateToYearStr(new Date());
		String endYear = ToolUtils.dateToYearStr(endDates);
		// 如果年不相同，需要将开始日期和结束日期设置为当年当月第一天和当年当月最后一天
		if (!year.equals(endYear)) {
			// 当月第一天
			startDates = TimeUtils.getDayOfMonth(new Date());
			// 当月最后一天
			endDates = TimeUtils.getLastDayOfMonth(new Date());
		}

		final Date startDate = startDates;
		final Date endDate = endDates;
		final List<Integer> employeeIdList = employeeIdLists;
		
			List<Employee> empList = new ArrayList<Employee>();
			if (employeeIdList == null || employeeIdList.size() == 0) {
				EmployeeExample employeeExample = new EmployeeExample();
				employeeExample.or().andFromDateLessThanOrEqualTo(endDate).andThruDateIsNull();
				employeeExample.or().andFromDateLessThanOrEqualTo(endDate).andThruDateGreaterThanOrEqualTo(startDate);
				empList = employeeDao.selectByExample(employeeExample);
				for (int i = 0; i < empList.size(); i++) {
					employeeIdList.add(empList.get(i).getEmployeeId());
				}
			} else {
				EmployeeExample employeeExample = new EmployeeExample();
				employeeExample.createCriteria().andEmployeeIdIn(employeeIdList);
				empList = employeeDao.selectByExample(employeeExample);
			}
			final List<Employee> empsList = empList;

			// 查询全部考勤打卡时间
			List<PunchTime> punchTimeList = punchTimeDao.selectByExample(new PunchTimeExample());
			Map<Integer, PunchTime> punchTimeMap = new HashMap<Integer, PunchTime>();
			for (int pi = 0; pi < punchTimeList.size(); pi++) {
				punchTimeMap.put(punchTimeList.get(pi).getPunchTimeId(), punchTimeList.get(pi));
			}

			// 查询班次情况
			EmployeeSchedulExample eslExample = new EmployeeSchedulExample();
			eslExample.setOrderByClause("employee_id asc,from_date desc");
			eslExample.createCriteria().andEmployeeIdIn(employeeIdList);
			List<EmployeeSchedul> eslList = employeeSchedulDao.selectByExample(eslExample);
			List<Integer> swIdsList = eslList.stream().map(EmployeeSchedul::getSwId).collect(Collectors.toList());

			// 查询班次日期
			SchedulDayExample sdExample = new SchedulDayExample();
			sdExample.createCriteria().andSwIdIn(swIdsList);
			List<SchedulDayKey> sdkList = schedulDayDao.selectByExample(sdExample);
			
			// 循环日期生成旷工
			Date curDates = DateUtils.addDays(new Date(startDate.getTime()), -1);
			String years = ToolUtils.dateToYearStr(new Date());
			Date day = new Date();
			while (curDates.compareTo(endDate) < 0) {
				curDates = DateUtils.addDays(curDates, 1);
				// 判断是否为当年
				String curYear = ToolUtils.dateToYearStr(curDates);
				if (curYear.equals(years)) {
					// 判断日期小于等于当前日期
					if (curDates.getTime() <= day.getTime()) {
						// 生成旷工人员考勤信息
						attendanceService.addNotAttendanceDate(curDates, employeeIdList, eslList, sdkList,
								punchTimeList, empsList);
					}
				}
			}
			// 取出包含当天的申请（不包含补签和加班申请）
			List<Integer> requestTypeList = new ArrayList<Integer>();
			requestTypeList.add(0);
			requestTypeList.add(1);
			requestTypeList.add(2);
			requestTypeList.add(3);
			requestTypeList.add(4);
			requestTypeList.add(5);
			requestTypeList.add(6);
			requestTypeList.add(8);
			requestTypeList.add(9);
			requestTypeList.add(11);
			requestTypeList.add(12);
			requestTypeList.add(13);

			List<Employee> employeeList = new ArrayList<Employee>();
			// 如果employeeIdList为空，取全员信息
			EmployeeExample employeeExample = new EmployeeExample();
			employeeExample.createCriteria().andEmployeeIdIn(employeeIdList);
			employeeList = employeeDao.selectByExample(employeeExample);

			// 查询历史申请
			RequestBean requestBean = new RequestBean();
			requestBean.setStartDate(startDate);
			requestBean.setEndDate(endDate);
			requestBean.setEmployeeIdList(employeeIdList);
			requestBean.setRequestTypeList(requestTypeList);
			requestBean.setApprovalState(2);
			List<Request> requestList = requestExtDao.getRequestByApprovalState(requestBean);

			// 取得申请通过的补签
			RetroactiveBean retroactiveBean = new RetroactiveBean();
			retroactiveBean.setEmployeeIdList(employeeIdList);
			retroactiveBean.setAttendanceDateStart(startDate);
			retroactiveBean.setAttendanceDateEnd(endDate);
			retroactiveBean.setApprovalState(2);
			List<Retroactive> retroactiveList = retroactiveExtDao.getRetroactiveByApprovalState(retroactiveBean);

			// 获取特殊情况
			EmployeeSpecialBean employeeSpecialBean = new EmployeeSpecialBean();
			employeeSpecialBean.setEmployeeIdList(employeeIdList);
			employeeSpecialBean.setStartDate(startDate);
			employeeSpecialBean.setEndDate(endDate);
			List<EmployeeSpecialKey> employeeSpecialKeyList = employeeSpecialExtDao
					.selectByEmployeeSpecialBean(employeeSpecialBean);

			// 查询特殊情况信息
			SpecialExample specialExample = new SpecialExample();
			specialExample.createCriteria().andSpecialDateBetween(startDate, endDate);
			List<Special> specialSList = specialDao.selectByExample(specialExample);
			Map<Integer, Special> specialMap = new HashMap<Integer, Special>();
			for (int si = 0; si < specialSList.size(); si++) {
				specialMap.put(specialSList.get(si).getSpecialId(), specialSList.get(si));
			}

			// 取得人员的排班时间
			EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
			employeeSchedulExample.createCriteria().andEmployeeIdIn(employeeIdList);
			employeeSchedulExample.setOrderByClause("sw_id desc");
			List<EmployeeSchedul> employeeSchedulDataList = employeeSchedulDao.selectByExample(employeeSchedulExample);
			// 获取班次集合
			List<Integer> swIdList = employeeSchedulDataList.stream().map(EmployeeSchedul::getSwId)
					.collect(Collectors.toList());
			// 查询固定班次
			SchedulWeekExample schedulWeekExample = new SchedulWeekExample();
			schedulWeekExample.createCriteria().andSwTypeEqualTo(1).andSwIdIn(swIdList);
			List<SchedulWeek> schedulWeekList = schedulWeekDao.selectByExample(schedulWeekExample);
			swIdList = new ArrayList<Integer>();
			Map<Integer, List<EmployeeSchedul>> employeeSchedulMap = new HashMap<Integer, List<EmployeeSchedul>>();
			for (int ei = 0; ei < employeeSchedulDataList.size(); ei++) {
				// 验证班次id是否存在
				Integer swId = employeeSchedulDataList.get(ei).getSwId();
				List<SchedulWeek> swList = schedulWeekList.stream().filter(s -> swId.equals(s.getSwId()))
						.collect(Collectors.toList());
				if (swList.size() <= 0) {
					continue;
				}
				if (employeeSchedulMap.containsKey(employeeSchedulDataList.get(ei).getEmployeeId())) {
					List<EmployeeSchedul> eList = employeeSchedulMap
							.get(employeeSchedulDataList.get(ei).getEmployeeId());
					eList.add(employeeSchedulDataList.get(ei));
					employeeSchedulMap.put(employeeSchedulDataList.get(ei).getEmployeeId(), eList);
				} else {
					List<EmployeeSchedul> eList = new ArrayList<EmployeeSchedul>();
					eList.add(employeeSchedulDataList.get(ei));
					employeeSchedulMap.put(employeeSchedulDataList.get(ei).getEmployeeId(), eList);
				}
				boolean swType = true;
				for (int si = 0; si < swIdList.size(); si++) {
					if (swIdList.get(si).equals(employeeSchedulDataList.get(ei).getSwId())) {
						swType = false;
						break;
					}
				}
				if (swType) {
					swIdList.add(employeeSchedulDataList.get(ei).getSwId());
				}
			}

			// 查询班次日期
			SchedulDayExample schedulDayExample = new SchedulDayExample();
			schedulDayExample.createCriteria().andSwIdIn(swIdList);
			List<SchedulDayKey> schedulDayKeyList = schedulDayDao.selectByExample(schedulDayExample);
			Map<Integer, List<SchedulDayKey>> schedulDayKeyMap = new HashMap<Integer, List<SchedulDayKey>>();
			for (int si = 0; si < schedulDayKeyList.size(); si++) {
				if (schedulDayKeyMap.containsKey(schedulDayKeyList.get(si).getSwId())) {
					List<SchedulDayKey> lList = schedulDayKeyMap.get(schedulDayKeyList.get(si).getSwId());
					lList.add(schedulDayKeyList.get(si));
					schedulDayKeyMap.put(schedulDayKeyList.get(si).getSwId(), lList);
				} else {
					List<SchedulDayKey> lList = new ArrayList<SchedulDayKey>();
					lList.add(schedulDayKeyList.get(si));
					schedulDayKeyMap.put(schedulDayKeyList.get(si).getSwId(), lList);
				}
			}

			// 查询哺乳假期
			List<LactationBean> lactationBeanList = lactationExtDao.getLactationEmployeeList(startDate, endDate,
					employeeIdList);
			Map<Integer, List<LactationBean>> lactationMap = new HashMap<Integer, List<LactationBean>>();
			for (int li = 0; li < lactationBeanList.size(); li++) {
				if (lactationMap.containsKey(lactationBeanList.get(li).getEmployeeId())) {
					List<LactationBean> lList = lactationMap.get(lactationBeanList.get(li).getEmployeeId());
					lList.add(lactationBeanList.get(li));
					lactationMap.put(lactationBeanList.get(li).getEmployeeId(), lList);
				} else {
					List<LactationBean> lList = new ArrayList<LactationBean>();
					lList.add(lactationBeanList.get(li));
					lactationMap.put(lactationBeanList.get(li).getEmployeeId(), lList);
				}
			}

			// 查询考勤信息
			AttendanceExample attendanceExample = new AttendanceExample();
			AttendanceExample.Criteria attendanceCriteria = attendanceExample.createCriteria();
			attendanceCriteria.andAttendanceDateBetween(startDate, endDate);
			attendanceCriteria.andEmployeeIdIn(employeeIdList);
			List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);

			// 查询人员无规律班次
			employeeSchedulExample = new EmployeeSchedulExample();
			employeeSchedulExample.createCriteria().andEmployeeIdIn(employeeIdList);
			List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
			// 获取班次ID
			List<Integer> swIdNoList = employeeSchedulList.stream().map(EmployeeSchedul::getSwId)
					.collect(Collectors.toList());
			// 查询无规律班次
			schedulWeekExample = new SchedulWeekExample();
			schedulWeekExample.createCriteria().andSwTypeEqualTo(2).andSwIdIn(swIdNoList);
			List<SchedulWeek> swNoList = schedulWeekDao.selectByExample(schedulWeekExample);
			// 存储无规律班次信息
			List<EmployeeSchedul> esNoList = new ArrayList<EmployeeSchedul>();
			for (int si = 0; si < swNoList.size(); si++) {
				Integer swId = swNoList.get(si).getSwId();
				List<EmployeeSchedul> list = employeeSchedulList.stream().filter(s -> swId.equals(s.getSwId()))
						.collect(Collectors.toList());
				if (list.size() > 0) {
					esNoList.addAll(list);
				}
			}
			// 获取班次内的日期
			swIdList = swNoList.stream().map(SchedulWeek::getSwId).collect(Collectors.toList());
			if (swIdList.size() > 0) {
				// 查询班次日期
				schedulDayExample = new SchedulDayExample();
				schedulDayExample.createCriteria().andSwIdIn(swIdList);
				schedulDayKeyList = schedulDayDao.selectByExample(schedulDayExample);
				for (int si = 0; si < schedulDayKeyList.size(); si++) {
					if (schedulDayKeyMap.containsKey(schedulDayKeyList.get(si).getSwId())) {
						List<SchedulDayKey> lList = schedulDayKeyMap.get(schedulDayKeyList.get(si).getSwId());
						lList.add(schedulDayKeyList.get(si));
						schedulDayKeyMap.put(schedulDayKeyList.get(si).getSwId(), lList);
					} else {
						List<SchedulDayKey> lList = new ArrayList<SchedulDayKey>();
						lList.add(schedulDayKeyList.get(si));
						schedulDayKeyMap.put(schedulDayKeyList.get(si).getSwId(), lList);
					}
				}
			}

			// 循环人员
			for (Employee employee : employeeList) {
				Integer employeeId = employee.getEmployeeId();
				// 控制循环用的
				Date curDate = DateUtils.addDays(new Date(startDate.getTime()), -1);
				while (curDate.compareTo(endDate) < 0) {
					curDate = DateUtils.addDays(curDate, 1);
					// 判断日期大于当天日期是，不计算考勤
					if (curDate.getTime() > new Date().getTime()) {
						break;
					}
					Integer punchTimeId = null;
					Integer swId = null; // 班次ID
					// 判断员工和班次关系是否存在
					if (employeeSchedulMap.containsKey(employeeId)) {
						// 判断员工所属日期范围
						List<EmployeeSchedul> eList = employeeSchedulMap.get(employeeId);
						// 循环判断日期范围是否匹配
						for (int ei = 0; ei < eList.size(); ei++) {
							EmployeeSchedul employeeSchedul = eList.get(ei);
							// 验证日期是否在区间内
							if (TimeUtils.dateCalendar(curDate, employeeSchedul.getFromDate(),
									employeeSchedul.getThruDate())) {
								punchTimeId = employeeSchedul.getPunchTimeId();
								swId = employeeSchedul.getSwId();
								break;
							}
						}
					}

					// 取得签到数据
					Attendance att = null;
					for (int ai = 0; ai < attendanceList.size(); ai++) {
						if (attendanceList.get(ai).getEmployeeId().equals(employeeId)) {
							// 验证日期是否在区间内
							if (curDate.equals(attendanceList.get(ai).getAttendanceDate())) {
								att = attendanceList.get(ai);
								break;
							}
						}
					}

					// 免签人员
					if (employee.getIsVisaWaiver() == 1) {
						if (att != null) {
							if (swId == null) {
								attendanceDao.deleteByPrimaryKey(att.getAttendanceId());
								continue;
							}

							// 取得打卡时间配置记录
							att.setAttendanceState(1);
							// 应出勤时长分钟数
							// Integer hoursMin = punchTime.getHours();
							// att.setActualHours(new BigDecimal(hoursMin));
							att.setUpdateTime(new Date());
							att.setDescription("免签人员");
							// 应出勤时长，除去休息
							// att.setAttendenceHours(new BigDecimal(hoursMin / 60));
							attendanceDao.updateByPrimaryKeySelective(att);
							continue;
						}
					}

					if (att == null) {
						continue;
					}

					// 判断员工考勤日期是否在无规律班次内
					Date attendanceDate = att.getAttendanceDate();
					List<EmployeeSchedul> list = esNoList.stream()
							.filter(s -> s.getEmployeeId().equals(employeeId) && s.getFromDate().equals(attendanceDate))
							.collect(Collectors.toList());
					if (list.size() > 0) {
						swId = list.get(0).getSwId();
						punchTimeId = list.get(0).getPunchTimeId();
					}

					// 判断当天的前一天是否为跨天班, 判断如果当天的考勤减一天，并且昨天的考勤时间为跨天时，将当天考勤删除。
					Date yesterday = DateUtils.addDays(curDate, -1);
					List<EmployeeSchedul> yesterlist = esNoList.stream()
							.filter(s -> s.getEmployeeId().equals(employeeId) && s.getFromDate().equals(yesterday))
							.collect(Collectors.toList());
					if (yesterlist.size() > 0) {
						PunchTime punchTime = punchTimeMap.get(yesterlist.get(0).getPunchTimeId());
						if (TimeUtils.compareTime(punchTime.getStartFromTime(), punchTime.getEndFromTime()) == 1) {
							AttendanceExample atExample = new AttendanceExample();
							atExample.createCriteria().andEmployeeIdEqualTo(employeeId)
									.andAttendanceDateEqualTo(curDate);
							List<Attendance> atList = attendanceDao.selectByExample(atExample);
							if (atList.size() > 0) {
								// 判断当天是否有班次
								Date fromDate = curDate;
								List<EmployeeSchedul> esList = esNoList.stream().filter(
										s -> s.getEmployeeId().equals(employeeId) && s.getFromDate().equals(fromDate))
										.collect(Collectors.toList());
								if (esList.size() <= 0) {
									// 判断签到时间和签退时间一致删除
									if (atList.get(0).getOriginalStartTime() == null
											&& atList.get(0).getOriginalEndTime() == null) {
										attendanceDao.deleteByPrimaryKey(atList.get(0).getAttendanceId());
										continue;
									} else {
										if (atList.get(0).getOriginalStartTime()
												.equals(atList.get(0).getOriginalEndTime())) {
											attendanceDao.deleteByPrimaryKey(atList.get(0).getAttendanceId());
											continue;
										}
									}
								} else {
									swId = esList.get(0).getSwId();
									punchTimeId = esList.get(0).getPunchTimeId();
								}
							}
						}
					}

					// 根据年月和员工ID，获取无规律班次
					List<Integer> eIdList = new ArrayList<>();
					eIdList.add(employeeId);
					List<SchedulWeekBean> dayCount = schedulWeekExtDao.getSchedulWeekDayCountByEmployeeId(eIdList,
							ToolUtils.dateToYearMonthStr(attendanceDate), attendanceDate);
					if (dayCount.size() > 0) {
						list = esNoList.stream().filter(
								s -> s.getEmployeeId().equals(employeeId) && s.getFromDate().equals(attendanceDate))
								.collect(Collectors.toList());
						if (list.size() <= 0) {
							att.setAttendanceState(9);
							att.setActualHours(new BigDecimal(0));
							att.setUpdateTime(new Date());
							attendanceDao.updateByPrimaryKeySelective(att);
							continue;
						}
					}

					if (swId == null && punchTimeId == null) {
						att.setAttendanceState(9);
						att.setActualHours(new BigDecimal(0));
						att.setUpdateTime(new Date());
						attendanceDao.updateByPrimaryKeySelective(att);
						continue;
					}

					att.setDescription("");
					// 用于存储计算的时间段
					List<String[]> datatimeList = new ArrayList<String[]>();

					// 取得打卡记录时间
					String stime = att.getOriginalStartTime();
					String etime = att.getOriginalEndTime();

					// 取得打卡时间配置记录
					PunchTime punchTime = null;
					if (punchTimeMap.containsKey(punchTimeId)) {
						punchTime = punchTimeMap.get(punchTimeId);
					}
					if (punchTime == null) {
						// 未找到打卡时间
						throw new ResultFaultException("5_00008");
					}

					// 判断是否为夜班考勤
					if (TimeUtils.compareTime(punchTime.getStartFromTime(), punchTime.getEndFromTime()) == 1) {
						// 根据当天日期+1将后台考勤读取出来
						Date afterDate = DateUtils.addDays(curDate, 1);
						AttendanceExample aExample = new AttendanceExample();
						aExample.createCriteria().andEmployeeIdEqualTo(employeeId).andAttendanceDateEqualTo(afterDate);
						List<Attendance> aList = attendanceDao.selectByExample(aExample);
						if (aList.size() > 0) {
							if (aList.get(0).getOriginalEndTime() != null) {
								etime = aList.get(0).getOriginalEndTime();
								att.setOriginalEndTime(etime);
							}
							// 判断日期是否存在班次内
							int count = 0;
							EmployeeSchedulExample esExample = new EmployeeSchedulExample();
							esExample.createCriteria().andEmployeeIdEqualTo(employeeId)
									.andFromDateGreaterThanOrEqualTo(afterDate).andThruDateLessThanOrEqualTo(afterDate);
							int record = employeeSchedulDao.countByExample(esExample);
							count += record;
							esExample = new EmployeeSchedulExample();
							esExample.createCriteria().andEmployeeIdEqualTo(employeeId)
									.andFromDateLessThanOrEqualTo(afterDate).andThruDateGreaterThanOrEqualTo(afterDate);
							record = employeeSchedulDao.countByExample(esExample);
							count += record;
							// 0 表示该日期内没有班次，需要删除
							if (count == 0) {
								attendanceDao.deleteByPrimaryKey(aList.get(0).getAttendanceId());
							}
						}
					}

					// 新员工入职，上班卡8：30
					if (employee.getEntryDate().equals(curDate)) {
						// 设置备注
						att.setDescription("入职当天上班卡默认为8:30，实际打卡时间:" + stime);
						stime = punchTime.getStartFromTime();
						att.setOriginalStartTime(stime);// 原始打卡时间更改为打卡上班开始时间
					}
					// 取得申请通过的补签
					if (retroactiveList != null && retroactiveList.size() > 0) {
						for (Retroactive retroactive : retroactiveList) {
							if (retroactive.getAttendanceId().equals(att.getAttendanceId())) {
								if (!StringUtils.isEmpty(retroactive.getStartTime())) {
									if (!StringUtils.isEmpty(att.getOriginalStartTime())) {
										if (TimeUtils.compareTime(retroactive.getStartTime(),
												att.getOriginalStartTime()) < 0
												|| TimeUtils.compareTime(att.getOriginalStartTime(), "04:00") < 0) {// 打卡时间过0点的情况
											stime = retroactive.getStartTime();
										} else {
											stime = retroactive.getStartTime();
										}
									} else {
										stime = retroactive.getStartTime();
									}
								}
								if (!StringUtils.isEmpty(retroactive.getEndTime())) {
									if (!StringUtils.isEmpty(att.getOriginalEndTime())) {
										etime = retroactive.getEndTime();// 直接取补签时间，不和原始值时间比较了。
									} else {
										etime = retroactive.getEndTime();
									}
								}
							}
						}
					}
					// 特殊打卡时间处理，11:45-12:00的打卡时间(开始吃饭时间点)
					if (etime != null) {
						if (TimeUtils.compareTime(etime, "11:45") >= 0 && TimeUtils.compareTime(etime, "12:00") <= 0) {
							etime = "12:00";
						}
					}
					if (!StringUtils.isEmpty(etime) && !StringUtils.isEmpty(stime)) {
						// 判断班次是否存在跨天
						// punchTime
						// 如果下班打卡小于6点，加24小时
						if (TimeUtils.compareTime(stime, "06:00") > 0 && TimeUtils.compareTime(etime, "06:00") <= 0) {
							// etime=TimeUtils.getEndTime(etime, 1440);
						}
					}
					// 特殊情况设置
					List<Integer> specialIdList = new ArrayList<>();
					if (employeeSpecialKeyList.size() > 0) {
						for (EmployeeSpecialKey employeeSpecialKey : employeeSpecialKeyList) {
							if (employeeSpecialKey.getEmployeeId().equals(employeeId)) {
								// 获取特殊情况
								if (specialMap.containsKey(employeeSpecialKey.getSpecialId())) {
									Special special = specialMap.get(employeeSpecialKey.getSpecialId());
									if (TimeUtils.dateCalendar(curDate, special.getSpecialDate(),
											special.getSpecialDate())) {
										specialIdList.add(employeeSpecialKey.getSpecialId());
									}
								}
							}
						}
					}
					if (specialIdList.size() > 0) {
						List<Special> specialList = new ArrayList<Special>();
						// 过滤特殊情况
						for (int sip = 0; sip < specialIdList.size(); sip++) {
							if (specialMap.containsKey(specialIdList.get(sip))) {
								Special special = specialMap.get(specialIdList.get(sip));
								specialList.add(special);
							}
						}
						if (specialList.size() > 0) {
							for (Special special : specialList) {
								String specialStartTime = special.getStartTime();
								String specialEndTime = special.getEndTime();
								// 考勤表添加特殊情况ID
								att.setSpecialId(special.getSpecialId());
								// 设置备注说明
								String description = "系统管理员设置特殊情况：" + special.getSpecialName();
								if (special.getDescription() != null) {
									description += "，说明(" + special.getDescription() + ")";
								}
								att.setDescription(description);
								if (!StringUtils.isEmpty(specialStartTime)) {
									if (!StringUtils.isEmpty(att.getOriginalStartTime())) {
										if (TimeUtils.compareTime(specialStartTime, att.getOriginalStartTime()) < 0) {
											stime = specialStartTime;
										}
									} else {
										stime = specialStartTime;
									}
								}
								if (!StringUtils.isEmpty(specialEndTime)) {
									if (!StringUtils.isEmpty(att.getOriginalEndTime())) {
										if (TimeUtils.compareTime(specialEndTime, att.getOriginalEndTime()) > 0) {
											etime = specialEndTime;
										}
									} else {
										etime = specialEndTime;
									}
								}
							}
						}
					}
					if (!StringUtils.isEmpty(stime) && !StringUtils.isEmpty(etime)) {
						datatimeList.add(new String[] { stime, etime });
					}
					// 计算实际出勤时间用
					String actStartTime = stime;
					String actEndTime = etime;

					// 考虑休息日的情况
					List<SchedulDayKey> schedulDayList = null;
					if (schedulDayKeyMap.containsKey(swId)) {
						schedulDayList = schedulDayKeyMap.get(swId);
						boolean type = true;
						// 循环判断日期范围是否匹配
						for (int si = 0; si < schedulDayList.size(); si++) {
							SchedulDayKey sdk = schedulDayList.get(si);
							// 验证日期是否在区间内
							if (sdk.getSdDate().equals(curDate)) {
								type = false;
								break;
							}
						}
						if (type) {
							schedulDayList = null;
						}
					}

					// 如果没查到数据，说明是休息日
					if (schedulDayList == null || schedulDayList.size() == 0) {
						att.setStartTime(actStartTime);
						att.setEndTime(actEndTime);
						att.setAttendanceState(9);
						att.setActualHours(new BigDecimal(0));
						att.setUpdateTime(new Date());
						attendanceDao.updateByPrimaryKeySelective(att);
						continue;
					}

					// 取得应出勤时长（包括中午休息）
					Integer punchMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(),
							punchTime.getEndFromTime());
					// 休假申请判断
					boolean isDay = false;// 是否假期是按天的类型
					// 合计申请时间
					Integer requestMinutes = 0;

					// 循环请假类型
					for (Request request : requestList) {
						if (!request.getEmployeeId().equals(employeeId)) {
							continue;
						}
						if (!TimeUtils.dateCalendar(curDate, request.getStartDate(), request.getEndDate())) {
							continue;
						}
						Integer requestType = request.getRequestType();
						// 按天请的假期
						if (requestType == 3 || requestType == 4 || requestType == 11 || requestType == 13) {
							att.setAttendanceState(1);
							att.setActualHours(new BigDecimal(0));
							att.setStartTime(actStartTime);
							att.setEndTime(actEndTime);
							att.setUpdateTime(new Date());
							attendanceDao.updateByPrimaryKeySelective(att);
							isDay = true;
						} else {
							if (request.getStartDate().compareTo(curDate) == 0
									&& request.getEndDate().compareTo(curDate) == 0) {
								// 申请一天内的情况
								datatimeList.add(new String[] { request.getStartTime(), request.getEndTime() });
							} else if (request.getStartDate().compareTo(curDate) == 0
									&& request.getEndDate().compareTo(curDate) > 0) {
								// 申请跨天第一天内的情况
								if (request.getStartToTime() == null) {
									// 取totime，班次
									datatimeList.add(new String[] { request.getStartTime(), punchTime.getEndToTime() });
								} else {
									datatimeList.add(new String[] { request.getStartTime(), request.getStartToTime() });
								}
							} else if (request.getStartDate().compareTo(curDate) < 0
									&& request.getEndDate().compareTo(curDate) == 0) {
								// 申请跨天最后一天内的情况
								if (TimeUtils.compareTime(request.getEndTime(), punchTime.getStartFromTime()) > 0) {
									datatimeList
											.add(new String[] { punchTime.getStartFromTime(), request.getEndTime() });
								}
							} else {
								// 请假中间天
								datatimeList
										.add(new String[] { punchTime.getStartFromTime(), punchTime.getEndFromTime() });
							}
							// 整天请假又有打卡的情况2018-02-26
							if (datatimeList.size() > 0) {
								// 判断如果员工为跨天班次
								if (TimeUtils.compareTime(punchTime.getStartFromTime(),
										punchTime.getEndFromTime()) == 1) {
									// 因申请可能出现跨天问题
									requestMinutes += TimeUtils.differMinutes(request.getStartTime(),
											request.getStartToTime());
									requestMinutes += TimeUtils.differMinutes(request.getStartToTime(),
											request.getEndTime());
									if (requestMinutes >= punchMinutes) {
										att.setAttendanceState(1);
										att.setActualHours(new BigDecimal(0));
										att.setStartTime(actStartTime);
										att.setEndTime(actEndTime);
										att.setUpdateTime(new Date());
										attendanceDao.updateByPrimaryKeySelective(att);
										isDay = true;
									}
								} else {
									String[] dtimes = datatimeList.get(datatimeList.size() - 1);
									String requestFromtime = dtimes[0];
									String requestTotime = dtimes[1];
									requestMinutes += TimeUtils.differMinutes(requestFromtime, requestTotime);
									if (requestMinutes >= punchMinutes) {
										att.setAttendanceState(1);
										att.setActualHours(new BigDecimal(0));
										att.setStartTime(actStartTime);
										att.setEndTime(actEndTime);
										att.setUpdateTime(new Date());
										attendanceDao.updateByPrimaryKeySelective(att);
										isDay = true;
									}
								}
							} else {
								// 判断如果员工为跨天班次
								if (TimeUtils.compareTime(punchTime.getStartFromTime(),
										punchTime.getEndFromTime()) == 1) {
									// 因申请可能出现跨天问题
									requestMinutes += TimeUtils.differMinutes(request.getStartTime(),
											request.getStartToTime());
									requestMinutes += TimeUtils.differMinutes(request.getStartToTime(),
											request.getEndTime());
									if (requestMinutes >= punchMinutes) {
										att.setAttendanceState(1);
										att.setActualHours(new BigDecimal(0));
										att.setStartTime(actStartTime);
										att.setEndTime(actEndTime);
										att.setUpdateTime(new Date());
										attendanceDao.updateByPrimaryKeySelective(att);
										isDay = true;
									}
								}
							}
						}
					}

					// 如果是当天申请多天通过后计算考勤是否正确
					if (isDay == false) {
						BigDecimal hours = new BigDecimal(0);
						// 循环请假类型
						for (Request request : requestList) {
							if (!request.getEmployeeId().equals(employeeId)) {
								continue;
							}
							if (curDate.getTime() == request.getStartDate().getTime()
									&& curDate.getTime() == request.getEndDate().getTime()) {
								Integer requestType = request.getRequestType();
								// 判断类型为调休
								if (requestType == 0 || requestType == 1 || requestType == 5 || requestType == 6) {
									if (request.getHours() != null) {
										Integer minutes = TimeUtils.differMinutes(request.getStartTime(),
												request.getEndTime());
										hours = hours.add(new BigDecimal(minutes));
									}
								}
							}
						}
						// 如果时间为当天班次时间为正常
						if (hours.intValue() >= punchMinutes) {
							att.setAttendanceState(1);
							att.setActualHours(new BigDecimal(0));
							att.setStartTime(actStartTime);
							att.setEndTime(actEndTime);
							att.setUpdateTime(new Date());
							attendanceDao.updateByPrimaryKeySelective(att);
							isDay = true;
						}

						// 判断调休时间加上签到时间
						if (att.getStartTime() != null && att.getEndTime() != null) {
							if (!att.getStartTime().equals(att.getEndTime())) {
								if (TimeUtils.compareTime(att.getStartTime(), punchTime.getEndFromTime()) == -1
										|| TimeUtils.compareTime(att.getStartTime(), punchTime.getEndFromTime()) == 0) {
									if (hours.intValue() > 0) {
										// 调休时间+加上打卡时间
										Integer dayMinutes = TimeUtils.differMinutes(att.getStartTime(),
												punchTime.getEndToTime());
										// 减去午休时间
										Integer noonbreakMinutes = TimeUtils.differMinutes(punchTime.getRestFromTime(),
												punchTime.getRestToTime());
										BigDecimal dayhours = new BigDecimal(dayMinutes);
										dayhours = dayhours.add(hours);
										Integer pMinutes = punchMinutes - noonbreakMinutes;
										if (dayhours.intValue() >= pMinutes) {
											att.setAttendanceState(1);
											att.setActualHours(new BigDecimal(0));
											att.setStartTime(actStartTime);
											att.setEndTime(actEndTime);
											att.setUpdateTime(new Date());
											attendanceDao.updateByPrimaryKeySelective(att);
											isDay = true;
										}
										
										if(isDay) {
											// 判断时长是否正确
											dayMinutes = TimeUtils.differMinutes(att.getStartTime(),att.getEndTime());
											dayhours = new BigDecimal(dayMinutes);
											dayhours = dayhours.add(hours);
											pMinutes = punchMinutes - noonbreakMinutes;
											if (dayhours.intValue() < pMinutes) {
												att.setAttendanceState(5);
												att.setActualHours(new BigDecimal(0));
												att.setStartTime(actStartTime);
												att.setEndTime(actEndTime);
												att.setUpdateTime(new Date());
												attendanceDao.updateByPrimaryKeySelective(att);
											}
											// 判断是否存在哺乳假
											if (lactationMap.containsKey(employeeId)) {
												isDay=false;
											}
										}
									}
								}
							}
						}
					}

					// 如果是按天申请的假期，不用后面比较
					if (isDay) {
						continue;
					}

					if (att != null) {
						// 判断如果日期为当天时，考勤状态不设置
						String date1 = ToolUtils.dateToStr(att.getAttendanceDate());
						// 获取当前日期
						String date2 = ToolUtils.dateToStr(new Date());
						if (date1.equals(date2)) {
							att.setAttendanceState(null);
							if (att.getOriginalStartTime() == null && att.getOriginalEndTime() == null) {
								att.setAttendanceState(5);
							} else {
								if (att.getOriginalStartTime().equals(att.getOriginalEndTime())) {
									att.setAttendanceState(null);
								}
							}
							att.setActualHours(new BigDecimal(0));
							att.setStartTime(actStartTime);
							att.setEndTime(actEndTime);
							att.setUpdateTime(new Date());
							attendanceDao.updateByPrimaryKey(att);
							continue;
						}
					}

					stime = "";
					etime = "";
					// 午休时间
					String restFromTime = punchTime.getRestFromTime();
					String restToTime = punchTime.getRestToTime();
					for (String[] datetimes : datatimeList) {
						if (stime == "") {
							stime = datetimes[0];
							etime = datetimes[1];
							if (requestMinutes > 0) {
								String[] ds = datatimeList.get(datatimeList.size() - 1);
								etime = ds[1];
							}
						}
						for (String[] dtimes : datatimeList) {
							if (TimeUtils.compareTime(stime, dtimes[0]) > 0
									&& (TimeUtils.compareTime(stime, dtimes[1]) <= 0
											|| (TimeUtils.compareTime(stime, restFromTime) >= 0
													&& TimeUtils.compareTime(dtimes[1], restToTime) <= 0))) {
								stime = dtimes[0];
							}
							if (TimeUtils.compareTime(etime, dtimes[1]) < 0
									&& (TimeUtils.compareTime(etime, dtimes[0]) >= 0
											|| (TimeUtils.compareTime(etime, restFromTime) >= 0
													&& TimeUtils.compareTime(dtimes[0], restToTime) <= 0))) {
								etime = dtimes[1];
							}
						}
					}

					// 判断哺乳假
					boolean isLactationTrue = false;// 是否是：如果都在弹性时间内，又时长不够，但小于30分钟，会被判定为早退的情况
					List<LactationBean> lactationList = null;
					if (lactationMap.containsKey(employeeId)) {
						lactationList = lactationMap.get(employeeId);
					}

					if (lactationList != null && lactationList.size() > 0) {
						isLactationTrue = true;
						// 循环判断日期是否在，哺乳假期范围内
						for (int lai = 0; lai < lactationList.size(); lai++) {
							LactationBean lab = lactationList.get(lai);
							if (TimeUtils.dateCalendar(curDate, lab.getHbornStartDate(), lab.getEndDate())) {
								// 取可休哺乳假时长
								BigDecimal bghours = lab.getHours();
								Integer lacHours = bghours.intValue();
								if (TimeUtils.compareTime(punchTime.getStartToTime(), stime) < 0
										|| TimeUtils.compareTime(punchTime.getStartToTime(), stime) == 1) {
									if(!stime.equals(etime)) {
										try {
											String[] times = stime.split(":");
											int hour = Integer.parseInt(times[0]);
											stime = String.valueOf(hour - lacHours) + ":" + times[1];
										} catch (Exception e) {
										}
										// 获取打开早上时间，判断是否大于班次的结束时间，如果大于设置为默认早上最晚结束时间
										if (att.getOriginalStartTime() != null) {
											if (TimeUtils.compareTime(att.getOriginalStartTime(),
													punchTime.getEndToTime()) > 0) {
												stime = punchTime.getStartToTime();
											}
										}
									}
									att.setDescription("早上休哺乳假期");
									isLactationTrue = false;
								}
									
								// 计算有效时间点
								if(!stime.equals(etime)) {
									if (TimeUtils.compareTime(punchTime.getStartFromTime(), stime) > 0) {
										stime = punchTime.getStartFromTime();
									}
								}
								
								if (TimeUtils.compareTime(punchTime.getEndToTime(), etime) < 0) {
									etime = punchTime.getEndToTime();
								}
								// 取得出勤时长
								Integer dayMinutes = TimeUtils.differMinutes(stime, etime);
								Integer startStatus = 1;
								Integer endStatus = 1;
								List<Integer> intList = this.calculationStatus(dayMinutes, punchMinutes, punchTime,
										stime, etime, isLactationTrue, startStatus, endStatus);
								startStatus = intList.get(0);
								endStatus = intList.get(1);
								if (startStatus == 1 && endStatus == 3) {
									isLactationTrue = true;
								} else if (startStatus == 5 && endStatus == 5) {
									isLactationTrue = true;
								}

								// if(TimeUtils.compareTime(punchTime.getEndFromTime(), etime)>0){
								if (isLactationTrue) {
									try {
										String[] times = etime.split(":");
										int hour = Integer.parseInt(times[0]);
										etime = String.valueOf(hour + lacHours) + ":" + times[1];
									} catch (Exception e) {
									}
									att.setDescription("晚上休哺乳假期");
									isLactationTrue = false;
								}
								// }
								break;
							}
						}
					}

					// 计算有效时间点
					/*
					 * if(TimeUtils.compareTime(punchTime.getStartFromTime(), stime)>0){ stime =
					 * punchTime.getStartFromTime(); }
					 * if(TimeUtils.compareTime(punchTime.getEndToTime(), etime)<0){ etime =
					 * punchTime.getEndToTime(); }
					 */

					// 取得出勤时长
					Integer dayMinutes = TimeUtils.differMinutes(stime, etime);

					// 判断出勤时间是否在考勤时间范围内
					if (TimeUtils.compareTime(stime, punchTime.getStartToTime()) > 0) {
						dayMinutes = 0;
					}
					Integer startStatus = 1;
					Integer endStatus = 1;
					// 出勤时间不够
					if (dayMinutes < punchMinutes) {
						if ((punchMinutes - dayMinutes) > 30) {// 如果缺勤时长大于30分钟，旷工
							startStatus = 5;
							endStatus = 5;
						}

						boolean isTrue = true;// 是否是：如果都在弹性时间内，又时长不够，但小于30分钟，早退

						if (stime != null && etime != null) {
							if (!stime.equals(etime)) {
								if (TimeUtils.compareTime(punchTime.getStartToTime(), stime) < 0) {
									if (TimeUtils.differMinutes(punchTime.getStartToTime(), stime) > punchTime
											.getStartInterval()) {
										// 早旷工
										startStatus = 5;
									} else {
										// 早迟到
										startStatus = 2;
										endStatus = 1;
									}
									isTrue = false;
								}

								if (isTrue && TimeUtils.compareTime(punchTime.getEndFromTime(), etime) > 0) {
									if (TimeUtils.differMinutes(etime, punchTime.getEndFromTime()) > punchTime
											.getEndInterval() || org.apache.commons.lang3.StringUtils.isBlank(etime)) {
										// 晚 旷工
										endStatus = 5;
									} else {
										// 晚 早退
										startStatus = 1;
										endStatus = 3;
									}
									isTrue = false;
								} else {
									if (isTrue && TimeUtils.differMinutes(etime,
											punchTime.getEndFromTime()) <= punchTime.getEndInterval()) {
										// 晚 早退
										startStatus = 1;
										endStatus = 3;
									} else {
										// 计算时间是否小于班次考勤时间
										Integer punchTimeMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(),
												punchTime.getEndFromTime());
										if (dayMinutes > 0 && dayMinutes < punchTimeMinutes) {
											// 晚 早退
											startStatus = 1;
											endStatus = 3;
										}
									}
								}
							}

							// 如果都在弹性时间内，又时长不够，但小于30分钟，早退
							/*
							 * if (isTrue) { if (isLactationTrue) {//
							 * 有哺乳假，但：如果都在弹性时间内，又时长不够，但小于30分钟，会被判定为早退的情况 // 正常
							 * att.setDescription("晚上休哺乳假期"); } else { // 晚 早退 endStatus = 3; } }
							 */
						}
					}

					// 验证上班时间是否正常
					/*
					 * if(startStatus==1 && endStatus==1) { if (dayMinutes<punchMinutes) {
					 * startStatus = 5; endStatus = 5; } }
					 */

					if (startStatus == 5 || endStatus == 5) {
						// 旷工
						att.setAttendanceState(5);
					} else if (startStatus == 2 && endStatus == 1) {
						// 迟到
						att.setAttendanceState(2);
					} else if (startStatus == 1 && endStatus == 3) {
						// 早退
						att.setAttendanceState(3);
					} else if (startStatus == 2 && endStatus == 3) {
						// 迟到并早退
						att.setAttendanceState(5);
					} else {
						// 正常
						att.setAttendanceState(1);
					}
					att.setStartTime(actStartTime);
					att.setEndTime(actEndTime);
					// 应出勤时长分钟数，除去休息
					Integer hoursMin = punchTime.getHours();
					if (StringUtils.isEmpty(actStartTime) || StringUtils.isEmpty(actEndTime)) {
						att.setActualHours(new BigDecimal(0));
					} else {
						Integer actMinutes = getMinutesRemoveRest(actStartTime, actEndTime, punchTime);
						if (actMinutes > hoursMin) {
							actMinutes = hoursMin;
						}
						att.setActualHours(new BigDecimal(actMinutes));
					}
					att.setAttendenceHours(new BigDecimal(hoursMin / 60));
					att.setUpdateTime(new Date());
					attendanceDao.updateByPrimaryKeySelective(att);

					if (att.getAttendanceDate().getTime() == new Date().getTime()) {
						// 处理当天考勤状态
						this.todayAttendance(new Date(), att.getEmployeeId());
					}
				}
			}

			// 循环删除考勤
			while (curDates.compareTo(endDate) < 0) {
				curDates = DateUtils.addDays(curDates, 1);
				// 判断是否为当年
				String curYear = ToolUtils.dateToYearStr(curDates);
				if (curYear.equals(years)) {
					// 判断日期小于等于当前日期
					if (curDates.getTime() <= day.getTime()) {
						// 删除休假日全部打开时间为空的数据
						attendanceExample=new AttendanceExample();
						attendanceExample.createCriteria()
						.andAttendanceDateEqualTo(curDates)
						.andAttendanceStateEqualTo(9)
						.andOriginalStartTimeIsNull()
						.andOriginalEndTimeIsNull()
						.andStartTimeIsNull()
						.andEndTimeIsNull();
						attendanceDao.deleteByExample(attendanceExample);
					}
				}
			}
			
			// 刪除重复考勤
			accessService.repeatAttendace();
		}catch (Exception e) {
			log.error("重计算错误：" + "==>" + e.getMessage());
			log.error(e,e);
			throw new ResultFaultException("0_00045");
		}
	}

	/**
	 * 处理当天考勤状态
	 * 
	 * @param startDate
	 */
	@Override
	public void todayAttendance(Date date, Integer employeeId) {
		if (employeeId != null) {
			AttendanceExample attendanceExample = new AttendanceExample();
			attendanceExample.createCriteria().andEmployeeIdEqualTo(employeeId).andAttendanceDateEqualTo(date);
			Attendance attendance = new Attendance();
			attendance.setAttendanceState(0);
			attendanceDao.updateByExampleSelective(attendance, attendanceExample);
			return;
		}
		List<Integer> attendanceIdList = attendanceExtDao.getAttendanceIdListByAttendanceDate(date);
		if (attendanceIdList.size() > 0) {
			AttendanceExample attendanceExample = new AttendanceExample();
			attendanceExample.createCriteria().andAttendanceIdIn(attendanceIdList);
			Attendance attendance = new Attendance();
			attendance.setAttendanceState(0);
			attendanceDao.updateByExampleSelective(attendance, attendanceExample);
		}
	}

	/**
	 * 验证考勤状态
	 * 
	 * @param dayMinutes
	 * @param punchMinutes
	 * @param punchTime
	 * @param stime
	 * @param etime
	 * @param isLactationTrue
	 * @param startStatus
	 * @param endStatus
	 */
	private List<Integer> calculationStatus(Integer dayMinutes, Integer punchMinutes, PunchTime punchTime, String stime,
			String etime, boolean isLactationTrue, Integer startStatus, Integer endStatus) {
		List<Integer> intList = new ArrayList<Integer>();
		// 出勤时间不够
		if (dayMinutes < punchMinutes) {
			if ((punchMinutes - dayMinutes) > 30) {// 如果缺勤时长大于30分钟，旷工
				startStatus = 5;
				endStatus = 5;
			} else {
				boolean isTrue = true;// 是否是：如果都在弹性时间内，又时长不够，但小于30分钟，早退
				if (TimeUtils.compareTime(punchTime.getStartToTime(), stime) < 0) {
					if (TimeUtils.differMinutes(punchTime.getStartToTime(), stime) > punchTime.getStartInterval()) {
						// 早旷工
						startStatus = 5;
					} else {
						// 早迟到
						startStatus = 2;
					}
					isTrue = false;
				}
				if (TimeUtils.compareTime(punchTime.getEndFromTime(), etime) > 0) {
					if (TimeUtils.differMinutes(etime, punchTime.getEndFromTime()) > punchTime.getEndInterval()) {
						// 晚 旷工
						endStatus = 5;
					} else {
						// 晚 早退
						endStatus = 3;
					}
					isTrue = false;
				}

				// 如果都在弹性时间内，又时长不够，但小于30分钟，早退
				if (isTrue) {
					if (isLactationTrue) {// 有哺乳假，但：如果都在弹性时间内，又时长不够，但小于30分钟，会被判定为早退的情况
					} else {
						// 晚 早退
						endStatus = 3;
					}
				}
			}
		}
		intList.add(startStatus);
		intList.add(endStatus);
		return intList;
	}

	/*
	 * 去掉午休后剩余时间
	 */
	private Integer getMinutesRemoveRest(String stime, String etime, PunchTime punchTime) {
		if (StringUtils.isEmpty(punchTime.getRestFromTime()) || StringUtils.isEmpty(punchTime.getRestToTime())) {
			return TimeUtils.differMinutes(stime, etime);
		}
		// 申请开始时间小于午休开始时间
		if (TimeUtils.compareTime(stime, punchTime.getRestFromTime()) < 0) {
			// 申请结束时间也小于等于 午休开始时间
			if (TimeUtils.compareTime(etime, punchTime.getRestFromTime()) <= 0) {
				return TimeUtils.differMinutes(stime, etime);
			} else {
				// 申请结束时间小于午休的结束时间
				if (TimeUtils.compareTime(etime, punchTime.getRestToTime()) < 0) {
					return TimeUtils.differMinutes(stime, punchTime.getRestFromTime());
				}
				// 申请结束时间大于等于午休的结束时间
				if (TimeUtils.compareTime(etime, punchTime.getRestToTime()) >= 0) {
					return TimeUtils.differMinutes(stime, punchTime.getRestFromTime())
							+ TimeUtils.differMinutes(punchTime.getRestToTime(), etime);
				}
			}
		} else {
			// 申请开始时间小于午休的结束时间
			if (TimeUtils.compareTime(stime, punchTime.getRestToTime()) < 0) {
				// 申请的结束时间大于午休的结束时间
				if (TimeUtils.compareTime(etime, punchTime.getRestToTime()) > 0) {
					return TimeUtils.differMinutes(punchTime.getRestToTime(), etime);
				} else {
					return 0;
				}
			} else {// 取申请的开始时间和申请的结束时间时间差
				return TimeUtils.differMinutes(stime, etime);
			}
		}
		return 0;
	}

	/*
	 * 计算打卡起止时间
	 */
	@Override
	public String[] getActAttendance(Date curDate, Integer employeeId) {

		// 取得人员的排班时间
		EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
		employeeSchedulExample.or().andEmployeeIdEqualTo(employeeId).andFromDateLessThanOrEqualTo(curDate)
				.andThruDateGreaterThanOrEqualTo(curDate);
		employeeSchedulExample.or().andEmployeeIdEqualTo(employeeId).andFromDateLessThanOrEqualTo(curDate)
				.andThruDateIsNull();
		employeeSchedulExample.setOrderByClause("from_date desc");
		List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
		if (employeeSchedulList == null || employeeSchedulList.size() == 0) {
			// 未找到排班信息,后续不处理
			return null;
		}

		// 取得签到数据
		AttendanceExample attendanceExample = new AttendanceExample();
		AttendanceExample.Criteria attendanceCriteria = attendanceExample.createCriteria();
		attendanceCriteria.andAttendanceDateEqualTo(curDate);
		attendanceCriteria.andEmployeeIdEqualTo(employeeId);
		List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);
		if (attendanceList == null || attendanceList.size() == 0) {
			return null;
		}
		Attendance att = attendanceList.get(0);

		// 取得申请通过的补签
		RetroactiveExample retroactiveExample = new RetroactiveExample();
		retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceList.get(0).getAttendanceId())
				.andApprovalStateEqualTo(2);
		List<Retroactive> retroactiveList = retroactiveDao.selectByExample(retroactiveExample);
		String stime = "";
		String etime = "";
		if (!StringUtils.isEmpty(att.getOriginalStartTime())) {
			stime = att.getOriginalStartTime();
		}
		if (!StringUtils.isEmpty(att.getOriginalEndTime())) {
			etime = att.getOriginalEndTime();
		}
		if (retroactiveList != null && retroactiveList.size() > 0) {
			for (Retroactive retroactive : retroactiveList) {
				if (!StringUtils.isEmpty(retroactive.getStartTime())) {
					if (!StringUtils.isEmpty(att.getOriginalStartTime())) {
						if (TimeUtils.compareTime(retroactive.getStartTime(), att.getOriginalStartTime()) < 0) {
							stime = retroactive.getStartTime();
						}
					} else {
						stime = retroactive.getStartTime();
					}
				}
				if (!StringUtils.isEmpty(retroactive.getEndTime())) {
					if (!StringUtils.isEmpty(att.getOriginalEndTime())) {
						if (TimeUtils.compareTime(retroactive.getEndTime(), att.getOriginalEndTime()) > 0) {
							etime = retroactive.getEndTime();
						}
					} else {
						etime = retroactive.getEndTime();
					}
				}
			}
		}
		// 特殊情况设置
		EmployeeSpecialExample esExample = new EmployeeSpecialExample();
		esExample.createCriteria().andEmployeeIdEqualTo(employeeId);
		List<EmployeeSpecialKey> employeeSpecialKeyList = employeeSpecialDao.selectByExample(esExample);
		List<Integer> specialIdList = new ArrayList<>();
		if (employeeSpecialKeyList.size() > 0) {
			for (EmployeeSpecialKey employeeSpecialKey : employeeSpecialKeyList) {
				specialIdList.add(employeeSpecialKey.getSpecialId());
			}
		}
		if (specialIdList.size() > 0) {
			SpecialExample sExample = new SpecialExample();
			sExample.createCriteria().andSpecialDateEqualTo(curDate).andSpecialIdIn(specialIdList);
			List<Special> specialList = specialDao.selectByExample(sExample);
			if (specialList.size() > 0) {
				for (Special special : specialList) {
					String specialStartTime = special.getStartTime();
					String specialEndTime = special.getEndTime();
					if (!StringUtils.isEmpty(specialStartTime)) {
						if (!StringUtils.isEmpty(att.getOriginalStartTime())) {
							if (TimeUtils.compareTime(specialStartTime, att.getOriginalStartTime()) < 0) {
								stime = specialStartTime;
							}
						} else {
							stime = specialStartTime;
						}
					}
					if (!StringUtils.isEmpty(specialEndTime)) {
						if (!StringUtils.isEmpty(att.getOriginalEndTime())) {
							if (TimeUtils.compareTime(specialEndTime, att.getOriginalEndTime()) > 0) {
								etime = specialEndTime;
							}
						} else {
							etime = specialEndTime;
						}
					}
				}
			}
		}
		return new String[] { stime, etime };
	}

	/*
	 * 计算考勤应结束时间
	 * 
	 * @param curDate
	 * 
	 * @param employeeId
	 */
	private String getAttendanceEndTime(Date curDate, Integer employeeId) {
		// 取出包含当天的申请（不包含补签和加班申请）
		List<Integer> requestTypeList = new ArrayList<Integer>();
		requestTypeList.add(0);
		requestTypeList.add(1);
		requestTypeList.add(2);
		requestTypeList.add(3);
		requestTypeList.add(4);
		requestTypeList.add(5);
		requestTypeList.add(6);
		requestTypeList.add(8);
		requestTypeList.add(9);
		requestTypeList.add(11);
		requestTypeList.add(12);
		requestTypeList.add(13);

		RequestExample example = new RequestExample();
		example.createCriteria().andStartDateLessThanOrEqualTo(curDate).andEndDateGreaterThanOrEqualTo(curDate)
				.andEmployeeIdEqualTo(employeeId).andRequestTypeIn(requestTypeList).andApprovalStateNotEqualTo(3);// 非拒绝的申请
																													// TODO
																													// test
																													// --update
																													// by
																													// zx
		List<Request> requestList = requestDao.selectByExample(example);

		// 取得人员的排班时间
		EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
		employeeSchedulExample.or().andEmployeeIdEqualTo(employeeId).andFromDateLessThanOrEqualTo(curDate)
				.andThruDateGreaterThanOrEqualTo(curDate);
		employeeSchedulExample.or().andEmployeeIdEqualTo(employeeId).andFromDateLessThanOrEqualTo(curDate)
				.andThruDateIsNull();
		employeeSchedulExample.setOrderByClause("from_date desc");
		List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
		if (employeeSchedulList == null || employeeSchedulList.size() == 0) {
			// 未找到排班信息,后续不处理
			return null;
		}

		// 取得签到数据
		AttendanceExample attendanceExample = new AttendanceExample();
		AttendanceExample.Criteria attendanceCriteria = attendanceExample.createCriteria();
		attendanceCriteria.andAttendanceDateEqualTo(curDate);
		attendanceCriteria.andEmployeeIdEqualTo(employeeId);
		List<Attendance> attendanceList = attendanceDao.selectByExample(attendanceExample);
		if (attendanceList == null || attendanceList.size() == 0) {
			return null;
		}
		Attendance att = attendanceList.get(0);

		// 用于存储计算的时间段
		List<String[]> datatimeList = new ArrayList<String[]>();

		// 取得申请通过的补签
		RetroactiveExample retroactiveExample = new RetroactiveExample();
		retroactiveExample.createCriteria().andAttendanceIdEqualTo(attendanceList.get(0).getAttendanceId())
				.andApprovalStateEqualTo(2);
		List<Retroactive> retroactiveList = retroactiveDao.selectByExample(retroactiveExample);
		String stime = att.getOriginalStartTime();
		String etime = att.getOriginalEndTime();
		if (retroactiveList != null && retroactiveList.size() > 0) {
			for (Retroactive retroactive : retroactiveList) {
				if (!StringUtils.isEmpty(retroactive.getStartTime())) {
					if (!StringUtils.isEmpty(att.getOriginalStartTime())) {
						if (TimeUtils.compareTime(retroactive.getStartTime(), att.getOriginalStartTime()) < 0) {
							stime = retroactive.getStartTime();
						}
					} else {
						stime = retroactive.getStartTime();
					}
				}
				if (!StringUtils.isEmpty(retroactive.getEndTime())) {
					if (!StringUtils.isEmpty(att.getOriginalEndTime())) {
						if (TimeUtils.compareTime(retroactive.getEndTime(), att.getOriginalEndTime()) > 0) {
							etime = retroactive.getEndTime();
						}
					} else {
						etime = retroactive.getEndTime();
					}
				}
			}
		}

		// 特殊情况设置
		EmployeeSpecialExample esExample = new EmployeeSpecialExample();
		esExample.createCriteria().andEmployeeIdEqualTo(employeeId);
		List<EmployeeSpecialKey> employeeSpecialKeyList = employeeSpecialDao.selectByExample(esExample);
		List<Integer> specialIdList = new ArrayList<>();
		if (employeeSpecialKeyList.size() > 0) {
			for (EmployeeSpecialKey employeeSpecialKey : employeeSpecialKeyList) {
				specialIdList.add(employeeSpecialKey.getSpecialId());
			}
		}
		if (specialIdList.size() > 0) {
			SpecialExample sExample = new SpecialExample();
			sExample.createCriteria().andSpecialDateEqualTo(curDate).andSpecialIdIn(specialIdList);
			List<Special> specialList = specialDao.selectByExample(sExample);
			if (specialList.size() > 0) {
				for (Special special : specialList) {
					String specialStartTime = special.getStartTime();
					String specialEndTime = special.getEndTime();
					if (!StringUtils.isEmpty(specialStartTime)) {
						if (!StringUtils.isEmpty(att.getOriginalStartTime())) {
							if (TimeUtils.compareTime(specialStartTime, att.getOriginalStartTime()) < 0) {
								stime = specialStartTime;
							}
						} else {
							stime = specialStartTime;
						}
					}
					if (!StringUtils.isEmpty(specialEndTime)) {
						if (!StringUtils.isEmpty(att.getOriginalStartTime())) {
							if (TimeUtils.compareTime(specialEndTime, att.getOriginalEndTime()) > 0) {
								etime = specialEndTime;
							}
						} else {
							etime = specialEndTime;
						}
					}
				}
			}
		}
		if (!StringUtils.isEmpty(stime) && !StringUtils.isEmpty(etime)) {
			datatimeList.add(new String[] { stime, etime });
		}

		// 取得打卡时间配置记录
		PunchTime punchTime = punchTimeDao.selectByPrimaryKey(employeeSchedulList.get(0).getPunchTimeId());

		// 取得应出勤时长
		Integer punchMinutes = TimeUtils.differMinutes(punchTime.getStartFromTime(), punchTime.getEndFromTime());

		for (Request request : requestList) {
			if (request.getStartDate().compareTo(curDate) == 0 && request.getEndDate().compareTo(curDate) == 0) {
				// 申请一天内的情况
				datatimeList.add(new String[] { request.getStartTime(), request.getEndTime() });
			} else if (request.getStartDate().compareTo(curDate) == 0 && request.getEndDate().compareTo(curDate) > 0) {
				// 申请跨天第一天内的情况
				if (request.getStartToTime() == null) {
					// 取totime，班次
					datatimeList.add(new String[] { request.getStartTime(), punchTime.getEndToTime() });
				} else {
					datatimeList.add(new String[] { request.getStartTime(), request.getStartToTime() });
				}
			} else if (request.getStartDate().compareTo(curDate) < 0 && request.getEndDate().compareTo(curDate) == 0) {
				// 申请跨天最后一天内的情况
				if (TimeUtils.compareTime(request.getEndTime(), punchTime.getStartFromTime()) > 0) {
					datatimeList.add(new String[] { punchTime.getStartFromTime(), request.getEndTime() });
				}
			} else {
				// 请假中间天
				datatimeList.add(new String[] { punchTime.getStartFromTime(), punchTime.getEndFromTime() });
			}
		}
		// 没有请假，也没有完整的考勤
		if (datatimeList == null || datatimeList.size() == 0) {
			return null;
		}

		stime = "";
		etime = "";
		// 午休时间
		String restFromTime = punchTime.getRestFromTime();
		String restToTime = punchTime.getRestToTime();
		for (String[] datetimes : datatimeList) {
			if (stime == "") {
				stime = datetimes[0];
				etime = datetimes[1];
			}
			for (String[] dtimes : datatimeList) {
				if (TimeUtils.compareTime(stime, dtimes[0]) > 0 && (TimeUtils.compareTime(stime, dtimes[1]) <= 0
						|| (TimeUtils.compareTime(stime, restFromTime) >= 0
								&& TimeUtils.compareTime(dtimes[1], restToTime) <= 0))) {
					stime = dtimes[0];
				}
				if (TimeUtils.compareTime(etime, dtimes[1]) < 0 && (TimeUtils.compareTime(etime, dtimes[0]) >= 0
						|| (TimeUtils.compareTime(etime, restFromTime) >= 0
								&& TimeUtils.compareTime(dtimes[0], restToTime) <= 0))) {
					etime = dtimes[1];
				}
			}
		}

		// 判断哺乳假
		LactationExample lacExample = new LactationExample();
		lacExample.createCriteria().andEmployeeIdEqualTo(employeeId).andHbornStartDateLessThanOrEqualTo(curDate)
				.andEndDateGreaterThanOrEqualTo(curDate);
		List<Lactation> lactationList = lactationDao.selectByExample(lacExample);
		// 如果有哺乳假
		Boolean isLactation = false;
		// 哺乳假时长
		Integer lacHours = 0;
		if (lactationList != null && lactationList.size() > 0) {
			isLactation = true;
			// 取可休哺乳假时长
			BigDecimal bghours = lactationList.get(0).getHours();
			lacHours = bghours.intValue();
			if (TimeUtils.compareTime(punchTime.getStartToTime(), stime) < 0) {
				isLactation = false;// 如果考勤时长不足，则哺乳假已使用
				try {
					String[] times = stime.split(":");
					int hour = Integer.parseInt(times[0]);
					stime = String.valueOf(hour - lacHours) + ":" + times[1];
				} catch (Exception e) {
				}
			} else if (TimeUtils.compareTime(punchTime.getEndFromTime(), etime) > 0) {
				isLactation = false;// 如果考勤时长不足，则哺乳假已使用
				try {
					String[] times = etime.split(":");
					int hour = Integer.parseInt(times[0]);
					etime = String.valueOf(hour + lacHours) + ":" + times[1];
				} catch (Exception e) {
				}
			}
		}

		// 计算有效时间点
		if (TimeUtils.compareTime(punchTime.getStartFromTime(), stime) > 0) {
			stime = punchTime.getStartFromTime();
		}
		if (TimeUtils.compareTime(punchTime.getEndToTime(), etime) < 0) {
			etime = punchTime.getEndToTime();
		}
		if (isLactation) {
			punchMinutes = punchMinutes - lacHours * 60;
		}
		String accEtime = TimeUtils.getEndTime(stime, punchMinutes);

		if (TimeUtils.compareTime(etime, accEtime) > 0) {
			return accEtime;
		} else {
			return etime;
		}
	}

	/**
	 * 计算早上加班时长（分钟）--张鑫
	 */
	@Override
	public Integer getMorningMinutes(RequestBean requestBean) {
		Date startDate = requestBean.getStartDate();
		// 加班开始时间
		String startTime = requestBean.getStartTime();
		// 加班结束时间
		String endTime = requestBean.getEndTime();
		Integer employeeId = requestBean.getEmployeeId();
		// 取得当天的考勤数据
		String[] attTimes = getActAttendance(startDate, employeeId);
		if (attTimes == null) {
			throw new ResultFaultException("4_00017");
		}
		String stime = attTimes[0];// 早上卡时间
		String etime = attTimes[1];// 早上卡时间
		if (StringUtils.isEmpty(stime) && !StringUtils.isEmpty(etime)) {
			// 考勤信息不完整
			throw new ResultFaultException("4_00014");
		} else if (!StringUtils.isEmpty(stime) && StringUtils.isEmpty(etime)) {
			// 考勤信息不完整
			throw new ResultFaultException("4_00014");
		} else if (StringUtils.isEmpty(stime) && StringUtils.isEmpty(etime)) {
			// 缺少考勤信息！
			throw new ResultFaultException("4_00017");
		}
		// 取得人员的排班时间
		EmployeeSchedulExample employeeSchedulExample = new EmployeeSchedulExample();
		employeeSchedulExample.or().andEmployeeIdEqualTo(employeeId).andFromDateLessThanOrEqualTo(startDate)
				.andThruDateGreaterThanOrEqualTo(startDate);
		employeeSchedulExample.or().andEmployeeIdEqualTo(employeeId).andFromDateLessThanOrEqualTo(startDate)
				.andThruDateIsNull();
		employeeSchedulExample.setOrderByClause("from_date Desc");
		List<EmployeeSchedul> employeeSchedulList = employeeSchedulDao.selectByExample(employeeSchedulExample);
		if (employeeSchedulList == null || employeeSchedulList.size() == 0) {
			// 未找到排班信息
			throw new ResultFaultException("5_00006");
		}
		// 取得打卡时间配置记录
		PunchTime punchTime = punchTimeDao.selectByPrimaryKey(employeeSchedulList.get(0).getPunchTimeId());
		String startFromTime = punchTime.getStartFromTime();
		// 比较早上打卡时间和申请开始时间
		if (TimeUtils.compareTime(stime, startTime) > 0) {
			throw new ResultFaultException("4_00009");
		}
		if (TimeUtils.compareTime(stime, etime) < 0) {
			// 申请结束时间endTime的比较
			if (TimeUtils.compareTime(startFromTime, endTime) < 0 || TimeUtils.compareTime(etime, endTime) < 0) {
				throw new ResultFaultException("4_00021");
			}
		}
		// 早上打卡时间和上班时间比较
		if (TimeUtils.compareTime(stime, startFromTime) > 0) {
			throw new ResultFaultException("4_00020");
		}
		// 计算早上加班时长
		if (TimeUtils.compareTime(startTime, stime) < 0) {
			startTime = stime;
		}
		if (TimeUtils.compareTime(endTime, startFromTime) > 0) {
			endTime = startFromTime;
		}
		Integer morningMinutes = TimeUtils.differMinutes(startTime, endTime);
		if (morningMinutes < 0) {
			throw new ResultFaultException("4_00018");
		}
		return morningMinutes;
	}

	/**
	 * 邮件提醒
	 * 
	 * @param employeeId  接收者id
	 * @param textPart    正文
	 * @param requestId   申请(或补签)id
	 * @param requestType 申请类型 99是补签，88是工资申请 忘记密码 requestId==null, requestType==null
	 */
	@Override
	public void sendEmail(Integer employeeId, String textPart, Integer kindsRequestId, Integer requestType) {

		// 查询初始化表
		SystemConfigure systemConfigure = systemConfigureDao.selectByPrimaryKey(1);
		if (systemConfigure.getIsMail() == 0 && kindsRequestId != null) {// kindsRequestId==null是重置密码
			// 不发邮件
		} else {
			// 接收者邮箱
			Employee employee = employeeDao.selectByPrimaryKey(employeeId);

			// 邮件内容
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			Date nowDate = new Date();
			long now = nowDate.getTime();
			String str = now + employee.getEmail();
			MD5Util md5 = new MD5Util();
			String key = md5.getMD5ofStr(str);

			// 把key(密钥)写入数据库地址表
			LinkAddress linkAddress = new LinkAddress();
			linkAddress.setEmployeeId(employee.getEmployeeId());
			linkAddress.setUrlKey(key);
			if (kindsRequestId == null) {// 忘记密码
				linkAddress.setType(0);// 1，是审批，，0，是忘记密码
			} else {// 申请
				linkAddress.setType(1);// 1，是审批，，0，是忘记密码
				// 设置申请id
				if (requestType == 99) {// 补签
					linkAddress.setRetroactiveId(kindsRequestId);
				} else if (requestType == 88) {// 工资申请
					linkAddress.setSalaryRequestId(kindsRequestId);
				} else {// 其它申请
					linkAddress.setRequestId(kindsRequestId);
				}
			}
			// pathNum
			String pathNum = null;
			if (requestType != null) {
				if (requestType == 7) {// 加班
					pathNum = "ot";// overtime
				} else if (requestType == 8) {// 出差
					pathNum = "bt";// businessTrip
				} else if (requestType == 9) {// 外出
					pathNum = "go";// goOut
				} else if (requestType == 99) {// 补签申请
					pathNum = "rr";// retroactiveRequest
				} else if (requestType == 88) {// 工资申请
					pathNum = "sr";// salaryRequest
				} else {// 其它申请
					pathNum = "or";// othersRequest
				}
			}
			linkAddressDao.insertSelective(linkAddress);

			String mailStr = null;
			String url = null;
			if (pathNum != null) {
				mailStr = MailUtils.toGBK(AppConstant.MAIL_APPROVAL_CONTENT);
				url = "key=" + key + "&pathNum=" + pathNum;
			} else {
				mailStr = MailUtils.toGBK(AppConstant.MAIL_FORGET_PASSWORD_CONTENT);
				url = "key=" + key;
			}
			textPart = textPart + mailStr.replace("@s", sdf.format(nowDate)).replace("@u", url);

			// 发邮件
			MailUtils.send(systemConfigure, employee.getEmail(), AppConstant.MAIL_TITLE, textPart,
					AppConstant.MAIL_ENDING);
		}
	}

	/**
	 * 驳回时发送邮件
	 * 
	 * @param employeeId
	 * @param textPart
	 */
	@Override
	public void sendEmailByReject(Integer employeeId, String textPart, String description) {
		// 查询初始化表
		SystemConfigure systemConfigure = systemConfigureDao.selectByPrimaryKey(1);
		if (systemConfigure.getIsMail() == 0) {
			// 不发邮件
		} else {
			// 接收者邮箱
			Employee employee = employeeDao.selectByPrimaryKey(employeeId);
			// 邮件内容
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			String rejcet = MailUtils.toGBK(AppConstant.MAIL_REJECT_CONTENT);
			if (description == null) {
				textPart = textPart + rejcet.replace("@s", sdf.format(new Date())).replace("@c", "");
			} else {
				textPart = textPart + rejcet.replace("@s", sdf.format(new Date())).replace("@c", description);
			}
			// 发邮件
			MailUtils.send(systemConfigure, employee.getEmail(), AppConstant.MAIL_TITLE, textPart,
					AppConstant.MAIL_ENDING);
		}
	}

	/**
	 * 删除一般申请的邮件链接key
	 * 
	 * @param kindsRequestId
	 */
	@Override
	public void deleteLinkAdd(Integer requestId) {
		LinkAddressExample laExample = new LinkAddressExample();
		laExample.createCriteria().andRequestIdEqualTo(requestId);
		linkAddressDao.deleteByExample(laExample);
	}

	/**
	 * 插入任务表数据
	 * 
	 * @param taskDate
	 * @param employeeId
	 */
	private void insertTask(Date taskDate, Integer employeeId) {
		Task task = new Task();
		task.setEmployeeId(employeeId);
		task.setState(0);
		task.setTaskDate(taskDate);
		taskDao.insertSelective(task);
	}

	/**
	 * 判断，然后插入任务表数据
	 */
	@Override
	public void insertTaskByParam(Date taskDate, Integer employeeId) {
		// 插入任务表数据
		TaskExample taskExample = new TaskExample();
		taskExample.createCriteria().andEmployeeIdEqualTo(employeeId).andTaskDateEqualTo(taskDate).andStateEqualTo(0);
		List<Task> taskList = taskDao.selectByExample(taskExample);// 查询是否已有数据
		if (taskList.size() == 0) {
			this.insertTask(taskDate, employeeId);
		}
	}
}
